\input texinfo.tex @c -*-texinfo-*-
@comment %**start of header
@setfilename djgppfaq.info
@set edition 2.11
@set update-date 13 September 1998
@set update-month September 1998
@settitle DJGPP FAQ List @value{edition}
@c @footnotestyle separate
@paragraphindent asis
@comment %**end of header
@include faqmacro.txi
@html
@ifclear html
@dircategory From faqNNNb.zip
@direntry
* FAQ: (djgppfaq). The DJGPP FAQ list.
@end direntry
@end ifclear
@finalout
@setchapternewpage odd
@titlepage
@c use the new format for titles
@title DJGPP Frequently-Asked Questions List
@subtitle Edition @value{edition}, for DJGPP Version 2.01
@subtitle @value{update-month}
@author by Eli Zaretskii
@comment Include the Distribution inside the titlepage so
@c that headings are turned off.
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1994, 1995, 1996, 1997, 1998 Eli Zaretskii
@end titlepage
@ifinfo
@htmltitle DJGPP Frequently-Asked Questions List
@htmlsubtitle Edition @value{edition}, for DJGPP Version 2.01
@htmlsubtitle @value{update-month}
@htmlauthor by Eli Zaretskii
@sp 1
@ifset html
@end ifset
@*
@*
This is the DJGPP Frequently-Asked Questions List.
@sp 1
Copyright (C) 1994, 1995, 1996, 1997, 1998 Eli Zaretskii.
@sp 1
@ifset html
@end ifset
This is the second edition of the FAQ list,@*
and is consistent with @w{version 2.01} of DJGPP.
@sp 1
@ifset html
@end ifset
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.
@end ifinfo
@ifinfo
@node Top, Urgent, (dir), (dir)
@top DJGPP FAQ List
In DJGPP (@pxref{DJGPP, DJGPP overview}), 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.
@paragraph{}
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 @b{;-)}
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.
@paragraph{}
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 @b{;-)}.
@paragraph{}
Some additional places to look for tutorials and other introductory
material about DJGPP are listed below.
@paragraph{}
One good place to look for DJGPP features that are often overlooked is
the @www{DJGPP Knowledge Base, www.delorie.com/djgpp/doc/kb/}. The
Knowledge Base is also available in Info format; type @samp{info
knowledge} from the DOS prompt. A @cite{User's Guide} is also being
written by several contributors; it is currently available @www{from the
DJGPP server, www.delorie.com/djgpp/doc/ug/}.
@paragraph{}
@mail{Brennan Underwood, brennan@@rt66.com} maintains a @www{home
page, brennan.home.ml.org/djgpp/}, which is another valuable source for
information about DJGPP.
@paragraph{}
You can browse the HTML version of this FAQ list on line at
@www{DJ Delorie's Web server,
www.delorie.com/djgpp/v2faq/faq.html}.
@paragraph{}
Also available from the DJ's server: @www{FAQ in several additional
formats, www.delorie.com/djgpp/v2faq/faq@value{faq-version}b.zip}.
@paragraph{}
A previous version of this FAQ was @ftp{translated into French,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2/frfaq@value{frfaq-version}b.zip},
also available @www{through the WWW,
www.delorie.com/djgpp/v2faq/frfaq@value{frfaq-version}.zip}.
@paragraph{}
This is Edition @value{edition} of the FAQ, last updated
@w{@value{update-date}}, for DJGPP Version 2.01.
@paragraph{}
@ifclear text
The following master menu lists the major topics in this FAQ list,
including all the indices.
@end ifclear
@c contents.idx is generated when the ASCII version is created
@ifset text
Table of Contents@*
*****************@*
@sp 2
@format
@include contents.idx
@end format
@*
@end ifset
@end ifinfo
@menu
* Urgent:: If you are in a hurry.
* DJGPP:: What is DJGPP?
* Requirements:: Hardware and software requirements for DJGPP.
* Getting DJGPP:: Where and what to download?
* Docs:: Where the documentation is and how to read it.
* Trouble:: When the compiler (or Make, or Info, or @dots{}) crashes
* Compiler performance:: How fast is the compiler?
* Compiling:: Compile-time and link-time problems.
* Running:: Running compiled programs.
* Graphics:: Graphics under DJGPP.
* Floating point:: Floating-point programs and FP emulation.
* Debugging:: Debugging DJGPP programs.
* Profiling:: Optimizing your programs.
* Performance:: Run-time performance of DJGPP programs.
* Memory:: Run-time memory issues.
* Command line:: Command-line arguments handling in DJGPP.
* Converting:: How to convert DOS code to DJGPP?
* Low-level:: Low-level and hardware-oriented programming.
* Legalese:: Legal aspects of programming with DJGPP.
* Help:: How to get more help.
* New versions:: Where are and what's new in latest DJGPP versions.
* Miscellany:: More@dots{}
* About:: Contributors to this FAQ.
* Topic Index:: Search here by a problem description.
* Program Index:: Search here by a program name.
@end menu
@node Urgent, DJGPP, Top, Top
@comment node-name, next, previous, up
@chapter If You Are In a Hurry
@quest{Do you really mean I have to read this looongish FAQ list to get my
answers?}
@quest{I have this problem which I absolutely MUST solve NOW! What do I
do?}
@ans{} No, you don't need to read @emph{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
@ifinfo
@ifset text
Table of Contents, at the beginning of this document.
@end ifset
@ifclear text
@ref{Top, Table of Contents}.
@end ifclear
@end ifinfo
@iftex
Table of Contents.
@end iftex
If that doesn't help, try the indices at the end of this manual. You
can look up your question either
@iftex
in
@end iftex
@ref{Program Index, by program name, Program Index}, or
@iftex
in
@end iftex
@ref{Topic Index, by topic name, Topic Index}.
@ifinfo
To search the indices in Info, press @kbd{i} (you don't need to go to
the Index node for that), then type the string you want to look up, and
press @key{Enter}. If the first place found by Info is not what you are
after, press @kbd{,} (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@footnote{
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.}.
@end ifinfo
For those in a @emph{real} hurry, here are some pointers to the most
important topics in this FAQ list:
@itemize @bullet
@item How to install DJGPP after downloading it?
@paragraph{}
Here's a brief description of the necessary steps:
@itemize @minus{}
@item
Create a directory for DJGPP and chdir there.
@paragraph{}
@item
Unzip all the @file{*.zip} files preserving the directory structure. On
Windows 9X, use an unzip program which supports long file names.
@paragraph{}
@item
Add these two lines to your @file{AUTOEXEC.BAT} file:
@example
set PATH=C:\DJGPP\BIN;%PATH%
set DJGPP=C:\DJGPP\DJGPP.ENV
@end example
@noindent
If your top DJGPP directory is other than @file{C:@bs{}DJGPP},
@strong{change these two lines accordingly!}
@paragraph{}
@item
Reboot your machine.
@end itemize
@paragraph{}
Your installation is now complete.
@paragraph{}
@item How do I compile and link programs?
@paragraph{}
Here are several simple commands:
@itemize @minus{}
@item Compile a single C source @file{cprog.c} into @file{cprog.exe}:
@paragraph
@example
gcc -o cprog.exe cprog.c
@end example
@paragraph{}
@item Compile a C@t{++} source @file{cxxprog.cc} into @file{cxxprog.exe}:
@paragraph{}
@example
gxx -o cxxprog.exe cxxprog.cc
@end example
@paragraph{}
@item Compile several C/C@t{++} source files into object files:
@paragraph{}
@example
gcc -c cfile1.c cxxfile2.cc
@end example
@paragraph{}
@item Link several @file{*.o} object files into @file{myprog.exe}:
@paragraph{}
@example
gxx -o myprog.exe cfile1.o cxxfile2.o
@end example
@end itemize
@paragraph{}
To compile with optimizations, add the @samp{-O2} switch to the command
line. In addition, use of the @samp{-Wall} switch is highly
recommended: it turns on many useful diagnostic messages.
@paragraph{}
@item How to ask experienced DJGPP users for help?
@paragraph{}
Use the DJGPP News group or mailing list. For most questions, you will
have your answer in a day or two. @xref{Totally lost, the details on how
to ask the gurus, How to ask DJGPP gurus for help}.
@paragraph{}
@item What is the best way to configure my system for DJGPP?
@paragraph{}
This depends on your hardware and software. Detailed instructions are
in @ref{Config, system configuration guidelines, How to configure your
system for DJGPP}.
@paragraph{}
@item Some files I need seem to be missing. Where do I find them?
@paragraph{}
Check out @ref{What to download, list of required and optional packages,
What files to download}.
@paragraph{}
@item How do I subscribe to or unsubscribe from the DJGPP mailing list?
@paragraph{}
@xref{Subscribing, subscription instructions, How to become a subscriber
to the mailing list}. However, it is better to read
@news{comp.os.msdos.djgpp} if you have access to Usenet News.
@paragraph{}
@item How can I search News group/mailing list traffic for some info?
@paragraph{}
This FAQ includes @ref{Deja vu, description of DJGPP archive search
server, How to search DJGPP archives for similar problems}. That search
facility is set up by @DJ{}, and you should use it whenever you have any
questions or look for an information on a DJGPP-related subject.
@end itemize
@node DJGPP, Requirements, Urgent, Top
@comment node-name, next, previous, up
@chapter What is DJGPP?
@cindex DJGPP, what it is
@quest{What is DJGPP?}
@ans{} 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.
@paragraph{}
The originator and principal maintainer of DJGPP is @DJ{}; that's where
the ``DJ'' in ``DJGPP'' comes from. However, anybody is welcome and
encouraged to contribute.
@paragraph{}
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 @dfn{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.
@paragraph{}
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. @xref{Windows apps,
writing Windows applications with DJGPP, MS-Windows applications and
DJGPP}.
@paragraph{}
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).
@paragraph{}
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 @ref{Application
distribution, (un)restrictions on distribution of DJGPP apps, Legal
(un)restrictions on DJGPP applications}.)
@paragraph{}
The core of DJGPP is the MS-DOS port of the GNU C/C@t{++} 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.
@paragraph{}
DJGPP presents a set of tools which are remarkably ANSI- and
Posix-compliant@footnote{
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.}. 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 @code{fork} system
call, are unimplemented); the C@t{++} 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.
@paragraph{}
Here are some of the tasks that DJGPP is said to be good for:
@itemize @minus{}
@item
learning C and C++ programming and teaching others to program in
C/C@t{++};
@item
using Unix development tools on MS-DOS and MS-Windows;
@item
writing games@footnote{
For example, the DOS version of the well-known game @samp{Quake} by id
Software was compiled with DJGPP.} and graphics programs;
@item
setting up a common development environment for Unix and
MS-DOS/MS-Windows;
@item
writing portable DOS/Unix programs;
@item
porting Unix programs to Microsoft operating systems.
@end itemize
DJGPP is also used as back-end for programming languages other than
C/C@t{++}. ADA, Pascal and Fortran compilers have been ported to MS-DOS
based on DJGPP (GNU Pascal (@samp{gpc}) and GNU Fortran (@samp{g77}) are
available from the DJGPP archives).
@paragraph{}
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, @w{4 GByte} flat address space and up
to 512 MBytes of virtual memory.
@node Requirements, Getting DJGPP, DJGPP, Top
@comment node-name, next, previous, up
@chapter Hardware and Software Requirements
@cindex Hardware requirements
@cindex Required hardware, general
@cindex Compatibility, hardware, general
@cindex Compatibility, operating systems, general
This chapter describes what are the hardware and software which will
allow you to use DJGPP. Minimum, ``reasonable'' and optimal system
configurations are listed.
@menu
* Minimum:: You cannot run DJGPP unless you have this.
* OS2:: But it crashes under OS/2!
* WindowsNT:: Is it compatible with Windows/NT?
* DOSEmu:: Can I run it on Linux?
* i286:: Why not?
* Windows apps:: Can I write Windows applications with DJGPP?
* Optimal hardware:: Here is your dream machine description.
* Reasonable hardware:: For the rest of us.
* Config:: How to configure your system software for DJGPP.
* More than 64MB:: How to set up your system for maximum memory.
@end menu
@node Minimum, OS2, Requirements, Requirements
@comment node-name, next, previous, up
@section The minimum system requirements for using DJGPP
@cindex Minimal hardware requirements
@cindex Hardware requirements, minimal
@cindex i386SX
@cindex Disk space, required for installation
@cindex System RAM, minimum
@cindex Minimum system RAM
@cindex Minimum system RAM, CWSDPMI
@cindex Recommended system RAM, for C programs compilation
@cindex Recommended system RAM, for C@t{++} programs compilation
@cindex C programs compilation, recommended system RAM
@cindex C@t{++} programs compilation, recommended system RAM
@cindex DPMI services, required to run DJGPP
@cindex DPMI services, problems with Novell NWDOS 7
@cindex Compatibility, Windows 3.X
@cindex Compatibility, Windows 9X
@cindex Compatibility, OS/2
@cindex Compatibility, Warp
@cindex Compatibility, Windows/NT
@cindex Compatibility, Novell NWDOS 7
@cindex Compatibility, Linux
@pindex Windows 3.X, compatibility
@pindex Windows 9X, compatibility
@pindex OS/2, compatibility
@pindex Warp, compatibility
@pindex Windows/NT, compatibility
@pindex Novell NWDOS 7, compatibility
@pindex Novell NWDOS 7, buggy DPMI services
@pindex Linux, compatibility
@pindex CWSDPMI, minimum required system RAM
@quest{What are the minimum system requirements for using DJGPP?}
@quest{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?}
@ans{} DJGPP requires at least 386SX CPU and between 15 and 35 MB of
free disk space (@pxref{Disk space, more details on this below, How much
disk space will I need}), 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@t{++} 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).
@paragraph{}
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.
@node OS2, WindowsNT, Minimum, Requirements
@comment node-name, next, previous, up
@section Does it really work under OS/2?
@cindex Spawning child processes, OS/2
@cindex Child processes, spawning under OS/2
@cindex Incompatibilities, OS/2
@cindex Incompatibilities, OS/2
@cindex Incompatibilities, Warp
@pindex OS/2, incompatibilities
@pindex OS/2 and RHIDE
@pindex Warp, incompatibilities
@pindex Make crashes on OS/2
@pindex RHIDE aborts on OS/2
@quest{You tell me it will work under OS/2, but I'm experiencing strange
crashes after several compilations @dots{}}
@quest{DJGPP Make crashes when I run it on OS/2!}
@ans{} 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 @samp{DPMI_DOS_API}. Setting it
to @samp{ENABLED} instead of the default @samp{AUTO} should solve the
problem. I'm also told that experimenting with the value of
@samp{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.
@paragraph{}
One particular problem with OS/2 v3.0 is that @sc{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.
@paragraph{}
If the above doesn't help, please post the details of the crashes you
see to the DJGPP mailing list (@pxref{Mailing list, how to post to the
mailing list, How to post to the mailing list}), or to
@news{comp.os.msdos.djgpp}, and somebody will help you.
@node WindowsNT, DOSEmu, OS2, Requirements
@comment node-name, next, previous, up
@section Will it work under Windows/NT?
@cindex Incompatibilities, Windows/NT
@cindex Long Filenames aren't supported on Windows/NT
@cindex LFN API, not supported by Windows/NT
@cindex LFN driver for NT, alpha version
@cindex Cygnus GCC port to Windows
@cindex Graphics, limitations on Windows/NT
@cindex Direct hardware access on Windows/NT
@cindex Spawning child programs on Windows/NT and 9X
@cindex Programs using nearptr fail on Windows/NT
@pindex Windows/NT doesn't allow port I/O
@pindex Windows/NT DPMI server loses selectors calling spawnXX
@pindex Windows/NT LFN driver
@pindex Windows 9X DPMI server loses selectors calling spawnXX
@quest{What about Windows NT?}
@ans{} 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).
@paragraph{}
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 @code{spawnXX} family you can see
an error message like this:
@example
Load error: no DPMI selectors
@end example
This problem is likely to afflict only DJGPP ports of Unix shells (such
as @samp{bash}), since no other DJGPP program, not even @samp{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 @samp{Make} sometimes fails on long @file{Makefiles} on
Windows 9X, where the selectors are lost at even higher rate than on NT.
If you ever run a very long @file{Makefile} and see @samp{Make} crash,
just run @samp{Make} again, and it will pick up where the crashed
session has left off.
@paragraph{}
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 @www{from Andrew's site,
www.goof.com/pcg/data/djgpp/lfn0106.zip}.
@paragraph{}
The popular DJGPP IDE @sc{rhide} needs a @samp{-M} switch to work on NT
(to disable the mouse support which will otherwise crash @sc{rhide}).
@paragraph{}
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 @file{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
@dfn{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.
@paragraph{}
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
@code{sbrk} algorithm in programs that run on Windows/NT. See the
library docs for the variable @code{_crt0_startup_flags} where the
@code{_CRT0_FLAG_UNIX_SBRK} bit is explained, for more info on this
issue. If you cannot switch to the Unixy @code{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.
@paragraph{}
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.
@paragraph{}
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. @xref{Windows
apps, , MS-Windows applications and DJGPP}, for more details about the
Cygnus ports.
@node DOSEmu, i286, WindowsNT, Requirements
@comment node-name, next, previous, up
@section Can it run under Linux?
@cindex Incompatibilities, Linux DOSEmu
@cindex DOSEmu, incompatibilities with DJGPP
@cindex DOSEmu, slow response to interactive programs
@cindex Compiling large programs on DOSEmu
@pindex Allegro, compiling on DOSEmu
@pindex Make crashes on DOSEmu
@pindex Linux, needs a patch to run nested programs
@pindex Linux, slow response to interactive programs
@quest{You say it works on Linux, but I seem to be unable to run the
compiler from within Make@dots{}}
@quest{I can run DJGPP on Linux, but Make crashes with SIGFPE on even
the simplest Makefiles!}
@quest{When I run bash on Linux/DOSEmu, echoing of what I type is very
slow.}
@ans{} 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 @www{DJGPP mail archives,
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 @ftp{on
the DJGPP ftp server,
ftp.delorie.com/pub/djgpp/contrib/dpmi-dosemu-djgpp.mail}.
@paragraph{}
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.
@paragraph{}
You might also need to edit the RAM section of the
@file{/etc/dosemu.conf} file to make it comfortable for DJGPP. I
suggest setting @samp{dpmi} and @samp{xms} to 16MB and @samp{ems} to
4MB. For example, I'm told that building the Allegro library with the
@samp{-O3} optimization switch fails in DOSEmu unless you allocate at
least 16MB of DPMI memory to DOSEmu sessions.
@paragraph{}
If DJGPP programs crash with an error message like this@footnote{
The typo in the word @samp{Exception} is in the actual message popped by
Linux.}:
@display
@cartouche
DPMI: Unhandled Execption 0d - Terminating Client
It is likely that dosemu is unstable now and should be rebooted
@end cartouche
@end display
@noindent
then you should add a line saying @samp{secure off} to your
@file{/etc/dosemu.conf} file.
Some users reported that @samp{Make}, and possibly other programs which
use floating point computations, crash in DOSEmu environment on systems
without an FPU, even if you set the @var{387} and @var{EMU387}
environment variables correctly (as explained in @ref{Emulation, Setting
up the FP emulator, Floating-point code without 80387}, 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.
@paragraph{}
@pindex Make, can be built to not issue FP instructions
@cindex Floating-point instructions and GNU Make
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.
@paragraph{}
If DJGPP programs respond too slow to keyboard input, you might need to
tune the @samp{HogThreshold} parameter in the @file{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.
@paragraph{}
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 @samp{rawkeyboard} to @file{dosemu.conf} might solve this.
@paragraph{}
@pindex RHIDE, mouse problems on DOSEmu
@pindex DOSEmu, RHIDE conflicts with mouse support
@cindex Mouse usage crashes RHIDE on DOSEmu
Some people complain that @sc{rhide} crashes on DOSEmu whenever the
mouse is moved. I'm told that using the @samp{-M} switch when invoking
@sc{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 @file{dosemu.conf}@footnote{
This was reported for DOSEmu version 0.66.7; the format of
@file{dosemu.conf} might be different in version 0.9x.}:
@example
serial @{ mouse com 2 device /dev/mouse @}
mouse @{mousesystems device /dev/mouse emulate3buttons @}
@end example
@noindent
and then load a DOS mouse driver in the DOSEmu @file{AUTOEXEC.BAT}.
@paragraph{}
@cindex VFAT32 support under DOSEmu
@cindex FAT32 support under DOSEmu
@pindex DOSEmu, problems with FAT32 volumes
If you have problems with mounting FAT32 partitions, upgrade the Linux
kernel to version 2.0.34 or later.
@node i286, Windows apps, DOSEmu, Requirements
@comment node-name, next, previous, up
@section Can I run it on a 286?
@cindex i286
@cindex Incompatibilities, i286
@quest{Why can't I run DJGPP on my 286? It has protected mode
also@dots{}}
@ans{} 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 @strong{is}
required.
@c
@c !!! Mention the activity to port GCC to 16-bit processors.
@c
@node Windows apps, Optimal hardware, i286, Requirements
@comment node-name, next, previous, up
@section MS-Windows applications and DJGPP
@cindex MS-Windows programming under DJGPP
@cindex Windows applications with DJGPP
@cindex Win32 programming with GCC
@cindex Windows 9X/NT programming with Cygnus GCC port
@cindex Cygnus port of GCC for Windows 9X and NT
@pindex RSXNTDJ toolkit for developing Win32 applications
@pindex Mingw32 port of GCC
@pindex lcc-win32 compiler for Windows
@quest{Can I write MS-Windows applications with DJGPP?}
@ans{} 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.
@paragraph{}
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.
@paragraph{}
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 @ftp{from SimTel,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2tk/rsxdj131.zip}.
@paragraph{}
@pindex RSXNTDJ, using with GCC 2.8.1 and later
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:
@itemize @bullet{}
@item
@cindex Resource compiler, doesn't work in RSXNTDJ
Add the directory where the pre-processor (@file{cpp.exe}) is kept to
the @code{PATH} environment variable. (Without this, the resource
compiler won't work.)
@item
Edit @file{DJGPP.ENV} to add the directories where the RSXNTDJ libraries
are kept to the value of the @code{LIBRARY_PATH} variable.
@item
@cindex Platform SDK, for RSXNTDJ
@cindex SDK, for RSXNTDJ
@pindex RSXNTDJ, MS Platform SDK
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
@www{Microsoft World Wide Web site,
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 @code{patch} utility fails.
@item
@cindex Undefined externals, with stdio functions and RSXNTDJ
I'm also told that the @file{stdio.h} header supplied with RSXNTDJ
defines several inline functions with the @code{extern} qualifier, which
causes GCC to not compile them into the object file, and triggers
undefined references. The solution is to define the @code{extern}
symbol to an empty string in one of the source files which includes the
@file{stdio.h} header.
@end itemize
@cindex Stack size, in RSXNTDJ programs
Some people report that they needed to bump up the stack size using the
@code{pestack} utility, allegedly due to insufficient size of the
default stack.
@paragraph{}
@cindex Linker, from RSXNTDJ, and unresolved externals
@cindex Undefined references, and the RSXNTDJ linker
@pindex ld.exe, from RSXNTDJ
Note that the version of linker @file{ld.exe} which comes with RSXNTDJ
doesn't print any message if you forget to link in libraries such as
@file{libcomct.a} and @file{libcomdl.a}. Instead, the produced
executables will die with SIGSEGV when run. Sometimes, forgetting to
@code{#include} @file{windows.h} also produces a program that crashes at
run time. You can use the stock DJGPP version of @file{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 @samp{nm} utility to find out
which libraries contain the required external symbols).
@paragraph{}
If RSXNTDJ doesn't suit your needs, you can use a few other compilers
which target Win32 platforms:
@table @code
@titem 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 @www{Cygnus site, www.cygnus.com/misc/gnu-win32/}, or
@ftp{via FTP, ftp.cygnus.com/pub/gnu-win32/latest/}.
@titem 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
(@file{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 @emph{free}.
For more details, visit the @www{Mingw32 home page,
www.xraylith.wisc.edu/~khan/software/gnu-win32/}.
@titem 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@t{++} 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
@www{Lcc home page, www.cs.princeton.edu/software/lcc/} and the
@www{lcc-win32 home page, www.cs.virginia.edu/~lcc-win32/}.
@end table
A better (but harder) way would be to volunteer to add Windows support to
DJGPP.
@node Optimal hardware, Reasonable hardware, Windows apps, Requirements
@comment node-name, next, previous, up
@section Machine you @emph{would like} to buy@dots{}
@cindex Configuration, the best
@cindex System configuration, the best
@cindex Environment variables, DJGPP
@quest{What is the optimal system configuration for running DJGPP?}
@ans{} Here is the description of your dream machine (at least for the
next 6 months @b{:-)}:
@itemize @bullet{}
@item
Hardware:
@itemize @minus{}
@item
the fastest CPU you can find on the market (a 400 MHz Pentium II, as of
this writing) with a 100 MHz memory bus;
@item
at least 512KB second-level (off-chip) cache memory;
@item
256 MByte RAM;
@item
PCI-based motherboard;
@item
SCSI-II hard disk with bus-mastering controller;
@end itemize
@item
Software:
@itemize @minus{}
@item
DOS, device drivers and TSRs all loaded HIGH, leaving only 5K DOS
footprint in lower (under 640K) memory;
@item
16 MByte RAM disk installed, @code{TMPDIR} environment variable points to
it (e.g., @kbd{set TMPDIR=e:}, if E: is the RAM drive letter);
@item
32 MByte of disk cache, set to delayed-write operation;
@end itemize
@end itemize
@node Reasonable hardware, Config, Optimal hardware, Requirements
@comment node-name, next, previous, up
@section Machine most of us will @emph{actually} buy @dots{}
@cindex Configuration, reasonable
@cindex Compiling large source files
@cindex Compiling GCC and CPP
@cindex Disk cache, when compiling large programs
@cindex RAM disk, when compiling large programs
@cindex Compiling large programs, disk cache settings
@cindex Compiling large programs, RAM disk settings
@pindex GCC, compiling, memory requirements
@pindex CPP, compiling, memory requirements
@quest{OK, I don't have this much money. What is the @strong{reasonable}
configuration?}
@ans{} If you have the following machine, you should be able to stop
worrying about memory and compilation performance:
@itemize @minus{}
@item
CPU: P133 with 256 KB off-chip cache;
@item
RAM: 32 MByte;
@item
Disk: 12 ms IDE with VLB controller, or SCSI;
@item
4 MByte RAM disk;
@item
8 MByte disk cache;
@end itemize
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 @emph{very} large source files, either reduce the disk cache
so you can give more to RAM disk, or point @code{TMPDIR} to your hard
disk and make the disk cache larger, if you can.
@node Config, More than 64MB, Reasonable hardware, Requirements
@comment node-name, next, previous, up
@section How to configure your system for DJGPP?
@cindex Configuration, for optimal performance
@cindex Optimal performance, system configuration
@cindex Disk cache, recommended settings
@cindex RAM disk, recommended settings
@cindex Optimal performance, disk cache settings
@cindex Optimal performance, RAM disk settings
@cindex Optimal performance, CWSDPMI tuning
@cindex Memory manager, settings for optimal performance
@cindex Compiling GCC and CPP, RAM disk
@cindex Slow compilation, tuning CWSDPMI
@cindex Machines with low extended RAM, tuning CWSDPMI
@cindex Excessive paging, tuning CWSDPMI
@cindex Tuning CWSDPMI for optimal performance
@pindex GCC, compiling, RAM disk
@pindex CPP, compiling, RAM disk
@pindex EMM386, settings for optimal performance
@pindex QEMM386, settings for optimal performance
@pindex CWSDPMI, setting parameters for optimal performance
@pindex CWSPARAM, a program to tune CWSDPMI performance
@pindex Windows, setting memory parameters for DJGPP
@quest{How do I configure my system to get optimal performance under
DJGPP?}
@ans{} That depends on the amount of RAM you have installed in your
machine. Below are some guidelines to help you.
@enumerate a
@item
If you have 2 MBytes or less RAM installed:
@itemize @bullet{}
@item
Don't use @strong{any} memory manager.
@item
Use of CWSDPMI as your DPMI host is highly recommended.
@item
Remove any TSR and device drivers you don't absolutely need (like
@file{SETVER.EXE}, @file{HIMEM.SYS} etc.) from your @file{CONFIG.SYS}
and @file{AUTOEXEC.BAT.}
@item
Do @strong{not} install disk cache or RAM disk; point your @code{TMPDIR}
environment variable to a directory on your hard disk. Put a
sufficiently large @samp{BUFFERS=} statement into your @file{CONFIG.SYS}
(I recommend setting @samp{BUFFERS=40,8}) to make DOS file operations
faster.
@item
If you use CWSDPMI as your DPMI host, get the @samp{CWSPARAM} program
(from the @file{csdpmi@value{csdpmi-version}b.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.
@item
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.
@end itemize
With this configuration, GCC will run out of free physical RAM and start
paging when compiling almost any C program and all C@t{++} programs. If
you are serious about DJGPP development, you need to buy more RAM
@strong{urgently}.
@item
If you have 2-4 MBytes of RAM installed:
@itemize @bullet{}
@item
Don't use @strong{any} memory manager.
@item
Remove any TSR and device driver you don't absolutely need (like
@file{SETVER.EXE}, @file{HIMEM.SYS}) from your @file{CONFIG.SYS} and
@file{AUTOEXEC.BAT.}
@item
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.
@item
Do @strong{not} install a RAM disk; point your @code{TMPDIR} environment
variable to a directory on your hard disk.
@item
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.
@end itemize
With this configuration, GCC will still run out of free physical RAM and
start paging when compiling large C programs and most C@t{++} programs.
Plan to buy more RAM as soon as you can.
@item
If you have 5-8 MBytes of RAM installed:
@itemize @bullet{}
@item
Use a memory manager such as @samp{EMM386} or @samp{QEMM386}. Try using
the @samp{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.
@item
Load DOS, device drivers and TSRs @strong{HIGH}.
@item
Give your disk cache 1 MByte of RAM. Enable its delayed-write (a.k.a.@:
write-back) feature.
@item
Do @strong{not} install a RAM disk; point your @code{TMPDIR} environment
variable to a directory on your hard disk.
@item
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@t{++} a lot),
enlarge the disk cache size.
@item
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.
@end itemize
@item
If you have more than 8 MBytes of RAM:
@itemize @bullet{}
@item
Use a memory manager to load DOS, TSRs and device drivers @strong{HIGH}.
@item
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.
@item
If you have more than 10 MBytes left, install a RAM disk with a size of at
least 1.5 MBytes and point your @code{TMPDIR} environment variable to it.
If your RAM disk is less than 4 MBytes, GCC might run out of space there
for @emph{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.
@item
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 @sc{rhide} or
Emacs, or to compile large source files.
@end itemize
@end enumerate
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
@samp{SmartDrv} disk cache, this is achieved by specifying @samp{/N/F}
switches instead of @samp{/X}.
@paragraph{}
A tutorial is available from the Web on @www{how to set up and get
started with DJGPP, www.castle.net/~avly/djgpp.html}.
@cindex Memory managers, recommended for use with DJGPP
Using a memory manager, such as @samp{EMM386} or @samp{QEMM}, is not
required (DJGPP will run without it), but highly recommended, since it
has several advantages:
@itemize @minus{}
@item
Memory managers provide an API for allocating extended memory called
VCPI (the @dfn{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.
@item
Without a memory manager, you cannot access UMBs (the @dfn{Upper Memory
Blocks}) which give you more DOS memory to work with. In particular,
CWSDPMI will load itself into UMBs if they are available.
@item
Memory managers provide the VDS (@dfn{Virtual DMA Services}) API which
allows to write programs that use DMA in protected mode.
@item
Memory managers support the expanded (EMS) memory, which some older DOS
programs still use.
@end itemize
@cindex Setting up DJGPP with EMM386
@pindex EMM386, getting the most memory
If your memory manager is @samp{EMM386}, I recommend to put the
@samp{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 @samp{EMM386}
limit your physical memory to 32MB.
@cindex Network installation
@cindex Installing DJGPP on networked drives
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 @file{nov-faq.htm}).
@node More than 64MB, , Config, Requirements
@comment node-name, next, previous, up
@section How to get the most RAM for DJGPP programs?
@cindex Physical memory, more than 64MB
@cindex OS/2 supports up to 512MB of DPMI memory
@pindex EMM386, how to get more than 32MB of memory
@pindex Windows 9X, how to get more than 64MB of DPMI memory
@pindex QEMM, how to get more than 64MB of memory
@quest{How do I set my system so that DJGPP programs could use all of my
256MB of installed physical RAM?}
@quest{I have 128MB of memory installed, but @code{go32-v2} only reports
32MB, how can I get more?}
@ans{} 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:
@itemize @bullet{}
@item
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 @emph{and} virtual memory combined, unless
you have more than 64MB installed physically, see below.)
@item
Do @strong{not} install any memory managers: most of them will limit the
amount of accessible memory to 64MB (@samp{EMM386} usually limits it to
32MB unless you turn off the VCPI support using the @samp{NOVCPI NOEMS}
parameters on the @samp{EMM386} command line). Using @samp{HIMEM} from
MS-DOS 7 does allow access to more than 64MB.
@item
If you are using @samp{QEMM} (version 8.0 or later), you must include
the @samp{USERAM=128M} parameter (here for 128MB of installed memory) on
its command line in your @file{CONFIG.SYS} and specify the exact amount
of memory installed on your machine, otherwise @samp{QEMM} won't support
more than 64MB.
@item
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.
@end itemize
Another possibility is to run your program from the Windows 9X DOS box,
after changing the @samp{EMM386} line in your @file{CONFIG.SYS} like
this:
@example
DEVICE=C:\WINDOWS\EMM386.EXE NOEMS L=131072
@end example
@noindent
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.
@paragraph{}
If you need to use more than 256MB of physical memory, try to convince
@CWS{} 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
@w{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).
@node Getting DJGPP, Docs, Requirements, Top
@comment node-name, next, previous, up
@chapter Where and What to Download?
@cindex DJGPP, how to get it
@cindex Getting DJGPP
This chapter explains where and how can you get DJGPP, and recommends
which parts of the archive you should download.
@menu
* Where to find:: Pick up from your nearest SimTel mirror.
* CCT:: Or look on one of the CCT mirrors.
* How to download:: Anonymous FTP, of course!
* DJGPP by WWW:: For those who use Netscape/Mosaic only.
* What to download:: Look here to decide what packages you need.
* Disk space:: How much disk storage do you need?
* DJGPP Fatware:: Can I do with less MBytes?
* Uninstall:: How to uninstall a DJGPP package.
@end menu
@node Where to find, CCT, Getting DJGPP, Getting DJGPP
@comment node-name, next, previous, up
@section Where can DJGPP be found?
@cindex Downloading DJGPP
@cindex DJGPP, where to download
@cindex SimTel mirrors' list
@cindex Differences between SimTel and CCT ftp sites
@quest{Where can I get DJGPP?}
@ans{} Look on any SimTel.NET mirror in the pub/simtelnet/gnu/djgpp/
subdirectory, or on one of the CCT mirrors, world-wide.
@paragraph{}
This section lists the SimTel.NET mirrors; see @ref{CCT, below, CCT
sites}, for the list of CCT sites.
@table @i
@titem The primary SimTel.NET site is:
@ftpdir{@SimTel{}, /pub/simtelnet/gnu/djgpp}@footnote{
@SimTel{} 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.}
@paragraph{}
@titem Here is a list of hosts by countries that offer mirror sites:
@sp 2
@titem Argentina
@ftpdir{ftp.satlink.com, /pub/mirrors/simtelnet/gnu/djgpp}
@titem Australia:
@ftpdir{ftp.tas.gov.au, /pub/simtelnet/gnu/djgpp}
@titem Australia:
@ftpdir{sunsite.anu.edu.au, /pub/pc/simtelnet/gnu/djgpp}
@titem Vienna, Austria:
@ftpdir{ftp.univie.ac.at, /mirror/simtelnet/gnu/djgpp}
@titem Brussels, Belgium:
@ftpdir{ftp.linkline.be, /mirror/simtelnet/gnu/djgpp}
@titem Sao Paulo, Brazil:
@ftpdir{ftp.unicamp.br, /pub/simtelnet/gnu/djgpp}
@titem Brazil:
@ftpdir{ftp.iis.com.br, /pub/simtelnet/gnu/djgpp}
@titem Ottawa, Canada:
@ftpdir{ftp.crc.doc.ca, /systems/ibmpc/simtelnet/gnu/djgpp}
@titem Vancouver, Canada:
@ftpdir{ftp.direct.ca, /pub/simtelnet/gnu/djgpp}
@titem Chile:
@ftpdir{sunsite.dcc.uchile.cl, /pub/Mirror/simtelnet/gnu/djgpp}
@titem Beijing, China:
@ftpdir{ftp.pku.edu.cn, /pub/simtelnet/gnu/djgpp}
@titem Czech Republic:
@ftpdir{ftp.eunet.cz, /pub/simtelnet/gnu/djgpp}
@titem Prague, Czech Republic:
@ftpdir{pub.vse.cz, /pub/simtelnet/gnu/djgpp}
@titem Czech Republic:
@ftpdir{ftp.zcu.cz, /pub/simtelnet/gnu/djgpp}
@titem Denmark:
@ftpdir{ftp.net.uni-c.dk, /pub/simtelnet/gnu/djgpp}
@titem Espoo, Finland:
@ftpdir{ftp.funet.fi, /mirrors/ftp.simtel.net/pub/simtelnet/gnu/djgpp}
@titem Neuilly, France:
@ftpdir{ftp.grolier.fr, /pub/simtelnet/gnu/djgpp}
@titem France:
@ftpdir{ftp.lip6.fr, /pub/simtelnet/gnu/djgpp}
@titem Germany:
@ftpdir{ftp.mpi-sb.mpg.de, /pub/simtelnet/gnu/djgpp}
@titem Bochum, Germany:
@ftpdir{ftp.rz.ruhr-uni-bochum.de, /pub/simtelnet/gnu/djgpp}
@titem Chemnitz, Germany:
@ftpdir{ftp.tu-chemnitz.de, /pub/simtelnet/gnu/djgpp}
@titem Heidelberg, Germany:
@ftpdir{ftp.uni-heidelberg.de, /pub/simtelnet/gnu/djgpp}
@titem Magdeburg, Germany:
@ftpdir{ftp.uni-magdeburg.de, /pub/mirrors/simtelnet/gnu/djgpp}
@titem Paderborn, Germany:
@ftpdir{ftp.uni-paderborn.de, /pub/simtelnet/gnu/djgpp}
@titem Trier, Germany:
@ftpdir{ftp.uni-trier.de, /pub/pc/mirrors/Simtel.net/gnu/djgpp}
@titem Wuerzburg, Germany:
@ftpdir{ftp.rz.uni-wuerzburg.de, /pub/pc/simtelnet/gnu/djgpp}
@titem Athens, Greece:
@ftpdir{ftp.ntua.gr, /pub/pc/simtelnet/gnu/djgpp}
@titem Hong Kong:
@ftpdir{ftp.cs.cuhk.hk, /pub/simtelnet/gnu/djgpp}
@titem Hong Kong:
@ftpdir{ftp.hkstar.com, /pub/simtelnet/gnu/djgpp}
@titem Hong Kong:
@ftpdir{sunsite.ust.hk, /pub/simtelnet/gnu/djgpp}
@titem Hungary:
@ftpdir{ftp.iif.hu, /pub/simtelnet/gnu/djgpp}
@titem Dublin, Ireland:
@ftpdir{ftp.heanet.ie, /pub/simtelnet/gnu/djgpp}
@titem Dublin, Ireland:
@ftpdir{ftp.iol.ie, /pub/simtelnet/gnu/djgpp}
@titem Rome, Italy:
@ftpdir{cis.uniroma2.it, /simtelnet/gnu/djgpp}
@titem Italy:
@ftpdir{ftp.flashnet.it, /pub/simtelnet/gnu/djgpp}
@titem Naples, Italy:
@ftpdir{ftp.unina.it, /pub/simtelnet/gnu/djgpp}
@titem Italy:
@ftpdir{mcftp.mclink.it, /pub/simtelnet/gnu/djgpp}
@titem Saitama, Japan:
@ftpdir{ftp.saitama-u.ac.jp, /pub/simtelnet/gnu/djgpp}
@titem Saitama, Japan:
@ftpdir{ftp.riken.go.jp, /pub/simtelnet/gnu/djgpp}
@titem Japan:
@ftpdir{ftp.iij.ad.jp, /pub/simtelnet/gnu/djgpp}
@titem Japan:
@ftpdir{ftp.u-aizu.ac.jp, /pub/PC/simtelnet/gnu/djgpp}
@titem Japan:
@ftpdir{ftp.web.ad.jp, /pub/simtelnet/gnu/djgpp}
@titem Latvia:
@ftpdir{ftp.lanet.lv, /pub/mirror/simtelnet/gnu/djgpp}
@titem Malaysia:
@ftpdir{ftp.jaring.my, /pub/simtelnet/gnu/djgpp}
@titem Mexico:
@ftpdir{ftp.gdl.iteso.mx, /pub/simtelnet/gnu/djgpp}
@titem Netherlands:
@ftpdir{ftp.euro.net, /d5/simtelnet/gnu/djgpp}
@titem Utrecht, Netherlands:
@ftpdir{ftp.nic.surfnet.nl, /mirror/simtelnet/gnu/djgpp}
@titem Bergen, Norway:
@ftpdir{ftp.bitcon.no, /pub/simtelnet/gnu/djgpp}
@titem Krakow, Poland:
@ftpdir{ftp.cyf-kr.edu.pl, /pub/mirror/Simtel.Net/gnu/djgpp}
@titem Warsaw, Poland:
@ftpdir{ftp.icm.edu.pl, /pub/simtelnet/gnu/djgpp}
@titem Poznan, Poland:
@ftpdir{ftp.man.poznan.pl, /pub/simtelnet/gnu/djgpp}
@titem Aveiro, Portugal:
@ftpdir{ftp.ua.pt, /pub/simtelnet/gnu/djgpp}
@titem Portugal:
@ftpdir{ftp.ip.pt, /pub/simtelnet/gnu/djgpp}
@titem Bucharest, Romania:
@ftpdir{ftp.digiro.net, /pub/simtelnet/gnu/djgpp}
@titem Timisoara, Romania:
@ftpdir{ftp.dnttm.ro, /pub/simtelnet/gnu/djgpp}
@titem Singapore:
@ftpdir{ftp.nus.sg, /pub/simtelnet/gnu/djgpp}
@titem Slovakia:
@ftpdir{ftp.uakom.sk, /pub/simtelnet/gnu/djgpp}
@titem Slovenia:
@ftpdir{ftp.arnes.si, /software/simtelnet/gnu/djgpp}
@titem Johannesburg, South Africa:
@ftpdir{ftp.is.co.za, /pub/simtelnet/gnu/djgpp}
@titem Stellenbosch, South Africa:
@ftpdir{ftp.sun.ac.za, /pub/simtelnet/gnu/djgpp}
@titem South Africa:
@ftpdir{ftp.netactive.co.za, /pub/simtelnet/gnu/djgpp}
@titem South Africa:
@ftpdir{ftp.saix.net, /pub/simtelnet/gnu/djgpp}
@titem South Korea:
@ftpdir{ftp.sogang.ac.kr, /pub/simtelnet/gnu/djgpp}
@titem South Korea:
@ftpdir{sunsite.snu.ac.kr, /pub/simtelnet/gnu/djgpp}
@titem Spain:
@ftpdir{ftp.rediris.es, /mirror/simtelnet/gnu/djgpp}
@titem Stockholm, Sweden:
@ftpdir{ftp.sunet.se, /pub/simtelnet/gnu/djgpp}
@titem Zurich, Switzerland:
@ftpdir{sunsite.cnlab-switch.ch, /mirror/simtelnet/gnu/djgpp}
@titem Chung-Li, Taiwan:
@ftpdir{ftp.ncu.edu.tw, /Packages/simtelnet/gnu/djgpp}
@titem Taipei, Taiwan:
@ftpdir{nctuccca.edu.tw, /mirror/simtelnet/gnu/djgpp}
@titem Nonthaburi, Thailand:
@ftpdir{ftp.nectec.or.th, /pub/mirrors/simtelnet/gnu/djgpp}
@titem London, UK:
@ftpdir{ftp.demon.co.uk, /pub/simtelnet/gnu/djgpp}
@titem London, UK:
@ftpdir{ftp.globalnet.co.uk, /pub/simtelnet/gnu/djgpp}
@titem Lancaster, UK:
@ftpdir{mic5.hensa.ac.uk, /mirrors/simtelnet/gnu/djgpp}
@titem London, UK:
@ftpdir{sunsite.doc.ic.ac.uk, /packages/simtelnet/gnu/djgpp}
@titem Concord, California, USA:
@ftpdir{ftp.cdrom.com, /pub/simtelnet/gnu/djgpp}
@titem California, USA:
@ftpdir{ftp.digital.com, /pub/micro/pc/simtelnet/gnu/djgpp}
@titem California, USA:
@ftpdir{ftp.lib.sonoma.edu, /pub/simtelnet/gnu/djgpp}
@titem Georgia, USA:
@ftpdir{ftp.peachnet.edu, /pub/mirrors/simtelnet/gnu/djgpp}
@titem Urbana, Illinois, USA:
@ftpdir{uarchive.cso.uiuc.edu, /pub/systems/pc/simtelnet/gnu/djgpp}
@titem Massachusets, USA
@ftpdir{ftp.bu.edu, /pub/mirrors/simtelnet/gnu/djgpp}
@titem Rochester, Michigan, USA:
@ftpdir{OAK.Oakland.Edu, /pub/simtelnet/gnu/djgpp}
@titem Missouri, USA:
@ftpdir{galileo.galilei.com, /pub/simtelnet/gnu/djgpp}
@titem New York, NY, USA:
@ftpdir{ftp.rge.com, /pub/systems/simtelnet/gnu/djgpp}
@titem Oklahoma, USA:
@ftpdir{ftp.ou.edu, /pub/simtelnet/gnu/djgpp}
@titem Corvallis, Oregon, USA:
@ftpdir{ftp.orst.edu, /pub/simtelnet/gnu/djgpp}
@titem Pennsylvania, USA:
@ftpdir{ftp.epix.net, /pub/simtelnet/gnu/djgpp}
@titem Virginia, USA:
@ftpdir{mirrors.aol.com, /pub/simtelnet/gnu/djgpp}
@paragraph{}
@end table
@node CCT, How to download, Where to find, Getting DJGPP
@comment node-name, next, previous, up
@section CCT sites
@cindex CCT mirrors' list
@quest{Where can I find the nearest CCT site?}
@ans{} 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 @file{Coast}. Therefore, if
you don't find the directories listed below, replace ``SimTel'' by
``Coast'' and try again.
@paragraph{}
@table @i
@titem The primary CCT site is in Detroit, Michigan, USA:
@ftpdir{@CCT{}, /Coast/vendors/djgpp/}.
@paragraph{}
@titem Here is a list of hosts by countries that offer mirror sites:
@sp 1
@titem Canberra, Australia:
@ftpdir{archie.au, /micros/pc/SimTel/vendors/djgpp}
@titem Edmonton, AB, Canada:
@ftpdir{ftp.agt.net, /pub/SimTel/vendors/djgpp}
@titem Prague, Czech Republic:
@ftpdir{pub.vse.cz, /pub/simtel/vendors/djgpp}
@titem London, England:
@ftpdir{src.doc.ic.ac.uk, /pub/packages/simtel/vendors/djgpp}
@titem Liverpool, England:
@ftpdir{ftp.mersinet.co.uk, /pub/ibmpc/coast/vendors/djgpp}
@titem London, England:
@ftpdir{ftp.demon.co.uk, /pub/mirrors/simtel/vendors/djgpp}
@titem Chemnitz, Germany:
@ftpdir{ftp.tu-chemnitz.de, /pub/simtel/vendors/djgpp}
@titem Mainz, Germany:
@ftpdir{ftp.uni-mainz.de, /pub/pc/mirrors/simtel/vendors/djgpp}
@titem Tuebingen, Germany:
@ftpdir{ftp.uni-tuebingen.de, /pub/simtel/vendors/djgpp}
@titem Hong Kong:
@ftpdir{ftp.cs.cuhk.hk, /pub/simtel/vendors/djgpp}
@titem Hong Kong:
@ftpdir{sunsite.ust.hk, /pub/simtel/vendors/djgpp}
@titem Dublin, Ireland:
@ftpdir{ftp.hea.ie, /pub/simtel/vendors/djgpp}
@titem Haifa, Israel:
@ftpdir{ftp.technion.ac.il, /pub/unsupported/simtel/vendors/djgpp}
@titem Naples, Italy:
@ftpdir{ftp.unina.it, /pub/simtel/vendors/djgpp}
@titem Pisa, Italy:
@ftpdir{cnuce-arch.cnr.it, /pub/msdos/simtel/vendors/djgpp}
@titem Rome, Italy:
@ftpdir{ftp.flashnet.it, /mirror/simtel/vendors/djgpp}
@titem Rome, Italy:
@ftpdir{cis.utovrm.it, /SimTel/vendors/djgpp}
@titem Tokyo, Japan:
@ftpdir{ftp.crl.go.jp, /pub/pc/archives/simtel/vendors/djgpp}
@titem Tokyo, Japan:
@ftpdir{ftp.web.ad.jp, /pub/mirrors/Coast/vendors/djgpp}
@titem Tokyo, Japan:
@ftpdir{ring.aist.go.jp, /pub/coast/vendors/djgpp}
@titem Tokyo, Japan:
@ftpdir{ring.asahi-net.or.jp, /pub/coast/vendors/djgpp}
@titem Seoul, Korea:
@ftpdir{ftp.kornet.nm.kr, /pub/SimTel/vendors/djgpp}
@titem Seoul, Korea:
@ftpdir{ftp.nowcom.co.kr, /pub/SimTel/vendors/djgpp}
@titem Utrecht, Netherlands:
@ftpdir{ftp.nic.surfnet.nl, /mirror-archive/software/simtel-vendors/djgpp}
@titem Poznan, Poland:
@ftpdir{ftp.man.poznan.pl, /mirror/simtel/vendors/djgpp}
@titem Warsaw, Poland:
@ftpdir{ftp.icm.edu.pl, /pub/simtel/vendors/djgpp}
@titem Moscow, Russia:
@ftpdir{ftp.radio-msu.net, /mirror/Coast/vendors/djgpp}
@titem Singapore:
@ftpdir{ftp.singnet.com.sg, /pub/mirrors/SimTel/vendors/djgpp}
@titem Slovak Republic:
@ftpdir{ftp.uakom.sk, /pub/SimTel/vendors/djgpp}
@titem Taipei, Taiwan:
@ftpdir{nctuccca.edu.tw, /PC/simtel/vendors/djgpp}
@titem Bangkok, Thailand:
@ftpdir{ftp.bu.ac.th, /pub/SimTel/vendors/djgpp}
@titem Sunnyvale, CA, USA:
@ftpdir{ftp.drcdrom.com, /Coast/vendors/djgpp}
@end table
Note that DJGPP was moved to the @file{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 @emph{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.
@node How to download, DJGPP by WWW, CCT, Getting DJGPP
@comment node-name, next, previous, up
@section How do I download DJGPP?
@cindex Downloading DJGPP with FTP
@cindex Downloading DJGPP via e-mail
@cindex DJGPP, downloading with FTP
@cindex FTP, downloading DJGPP
@quest{How do I download files from these sites?}
@ans{} FTP to the nearest site, log in as @kbd{anonymous}, give your
full e-mail address as password, and chdir to the @file{djgpp}
subdirectory (the exact path to it might be different on different
mirrors, check out @ref{Where to find, the DJGPP archive path, Where can
DJGPP be found}, for your nearest mirror). Then issue the @kbd{binary}
command and download the files you need (@pxref{What to download, the
list of required files, What files to download}) with the @samp{get} or
@samp{mget} commands.
@node DJGPP by WWW, What to download, How to download, Getting DJGPP
@comment node-name, next, previous, up
@section What if I don't know what @samp{FTP} is?
@cindex Downloading DJGPP with WWW
@cindex DJGPP, downloading with WWW
@cindex WWW, downloading DJGPP
@cindex DJGPP, downloading with Gopher
@cindex Gopher, downloading DJGPP
@cindex DJGPP, downloading via e-mail
@cindex E-mail, downloading DJGPP
@cindex CD-ROM, getting DJGPP
@cindex Getting DJGPP from a CD-ROM
@pindex Netscape, downloading DJGPP
@pindex Internet Explorer, downloading DJGPP
@quest{What is that @samp{FTP} thing? I only use @samp{Netscape} and
@samp{IE4} for Internet access.}
@ans{} OK, here are some Web sites for use with your Web browser:
@sp 2
@itemize @minus{}
@item
@www{The main SimTel.NET site, www.simtel.net/simtel.net/gnu/djgpp/}.
@item
@www{The main CCT site, www.coast.net/Coast/vendors/djgpp/}.
@end itemize
You can also convert any of the mirrors' addresses listed in @ref{Where
to find, the list of SimTel.NET mirrors, Where can DJGPP be found},
above to a valid URL by prepending @samp{ftp://} to it. For example,
the URL for FTP from @ftp{CCT,
@CCT{}/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.
@paragraph{}
Gopher users can get CCT files @gopher{with a Gopher client,
gopher.oakland.edu}.
@paragraph{}
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
@mail{CCT list server, listserv@@Coast.NET} with this command in
the message body:
@example
get simtel-mailserver.info
@end example
Another ftp-mail server is @url{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 @cite{DJGPP Development
System CDROM}. It includes @strong{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 @www{Walnut Creek Web site,
www.cdrom.com/titles/prog/x2ftp.htm}.
@paragraph{}
@mail{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 @email{set-soft@@usa.net}.
@node What to download, Disk space, DJGPP by WWW, Getting DJGPP
@comment node-name, next, previous, up
@section What Files to Download?
@cindex Files, minimum set to download
@cindex Packages, which to download
@cindex DJGPP, a list of packages
@cindex List of DJGPP packages
@cindex Packages, DJGPP, list of
@cindex DJGPP distribution, list of
@quest{What's the minimum set of @file{.zip} files I need to download?}
@ans{} 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 @www{use the DJGPP zip-picker feature, www.delorie.com/djgpp/} which
will guide you through the process.
@sp 1
@itemize @bullet{}
@item
@cindex Downloading, individual DJGPP files
@cindex Missing DJGPP files, downloading
@cindex Files, missing, where to download
To only run DJGPP-compiled programs, you MUST download all of
these@footnote{
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 @news{comp.os.msdos.djgpp}. 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 @www{on the DJGPP
server, www.delorie.com/djgpp/dl/ofc/}, which is also a convenient way
of downloading individual files if you have lost them somehow.}:
@paragraph{}
@table @file
@titem v2/readme.1st
This explains how to install DJGPP and get started with using it.
@titem v2/faq@value{faq-version}b.zip
The latest edition of this FAQ list. Use it whenever you have problems
installing and using DJGPP.
@titem v2/frfaq@value{frfaq-version}b.zip
The latest version of the FAQ translated into French by @mail{Francois
Charton, deef@@pobox.oleane.com}.
@titem v2misc/csdpmi@value{csdpmi-version}b.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.)
@titem v2misc/pmode@value{pmode-version}b.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.
@ignore
@titem v2/djtzn@value{djgpp-version}.zip
This archive includes the @dfn{timezone} files, which are used by
several library functions and programs that call those functions, to
translate file time stamps between different time zones. You will need
this archive if you run DJGPP-compiled programs that set file times for
files downloaded from a distant place; one example is an archiving
program such as @samp{unzip} or Tar. Most people will only need a
single file from this distribution. @xref{Zoneinfo, , What is in that
@file{zoneinfo} directory?}, for a detailed explanation of these files.
@end ignore
@end table
@paragraph{}
@item
For developing C programs (no C@t{++}), you MUST download all of the above,
plus the following:
@paragraph{}
@table @file
@titem v2gnu/bnu@value{bnu-version}b.zip
The GNU Binutils, including @code{as}, the GNU assembler; @code{ld}, the
GNU linker; and their docs. GCC calls these utilities during
compilation.
@titem v2/djdev@value{djgpp-version}.zip
C header files and libraries, library reference, minimal development
environment, DJGPP-specific utilities and their documentation. Required
to compile/link programs.
@titem v2gnu/gcc@value{gcc-version}b.zip
The GNU C Compiler binaries and docs (including the docs for the C@t{++}
compiler).
@titem v2gnu/txi@value{txi-version}b.zip
@pindex install-info, a program to install Info docs
@cindex Installation of Info docs, a utility
Info, a stand-alone program to read GNU hypertext documentation files, and
an environment to produce such files. Without @samp{info}, you cannot
read the C library reference and the docs included with the ported GNU
software packages. This package also includes the @samp{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.
@end table
@paragraph{}
@item
For developing C@t{++} programs, you will need all of the above, plus the
following:
@paragraph{}
@table @file
@titem v2gnu/gpp@value{gcc-version}b.zip
The GNU C@t{++} compiler binary (the docs are part of the gccNNNb.zip
package, see above), the C@t{++} header files and standard C@t{++} class
libraries, including the STL, and their docs.
@titem v2gnu/lgp@value{lgpp-version}b.zip
Additional GNU C@t{++} class libraries. This library is now deprecated
and no longer maintained. I suggest not to use it.
@titem v2gnu/obc@value{gcc-version}b.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 @www{from Brad Cox's home
page, www.virtualschool.edu/lang/objectivec/}.
@end table
@paragraph{}
@item
The following are some optional packages which you might want:
@paragraph{}
@itemize @minus{}
@item
Debugging:
@paragraph{}
@table @file
@titem v2gnu/gdb@value{gdb-version}b.zip
GDB, the GNU Debugger and its docs. (Note that the @code{djdev}
distribution includes two simpler, assembly-level debuggers,
@code{edebug} and @code{fsdb.} The latter presents a user interface
similar to that of Turbo Debugger.)
@end table
@paragraph{}
@item
Additional development tools (consider getting at least the Make
distribution):
@paragraph{}
@table @file
@titem v2gnu/mak@value{mak-version}b.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 @file{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 @file{COMMAND.COM} and its
@file{4DOS/NDOS} replacements) and can be used to run Unix Makefiles if
you install a Unix-style shell (e.g., @samp{bash}) and auxiliary
utilities. It also supports long filenames on Windows 9X and MS-DOS
pathnames with drive letters.
@titem v2apps/rhide@value{rhide-version}b.zip
The @sc{rhide} integrated development environment for DJGPP (similar to
Borland IDE), written by @mail{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
@samp{Gettext} library). Latest developments and beta versions of
@sc{rhide} are available @www{from its home page,
www.tu-chemnitz.de/~sho/rho/rhide.html}.
@titem v2/djlsr@value{djgpp-version}.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.
@ignore
Note that the sources for the time-zone-related
programs and files are available separately, in the
@file{djtzs@value{djgpp-version}.zip} archive.
@end ignore
@titem v2gnu/bsh@value{bsh-version}b.zip
Bash (@samp{Bourne-Again SHell}), the GNU shell, and its docs. If you
mostly work in Unix environment, you will feel right at home using
@samp{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 @samp{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.
@titem v2gnu/bsn@value{bsn-version}b.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.
@titem v2gnu/dif@value{dif-version}b.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
@samp{diff} program from this package. @samp{diff} is also required by
almost all configuration-management packages, such as @sc{rcs}.
@titem v2gnu/emacs.README
@titeml v2gnu/em@value{emacs-version}*.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 @sc{rhide}, see above). Please
read the file @file{emacs.README} before you begin downloading the rest.
@titem v2gnu/fil@value{fil-version}b.zip
GNU Fileutils, including @samp{ls}, @samp{rm}, @samp{cp}, @samp{mv}, and
others. Highlights of the latest port: @samp{ls} supports colorization
of files (like on Linux), @samp{ln -s} knows about DJGPP-style
``symlinks'' (see @ref{Symlinks, symlink feature of DJGPP, How to create
symbolic links to programs}, elsewhere in this document), @samp{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 @emph{a lot}.
@titem v2gnu/find@value{find-version}b.zip
GNU Findutils, including @samp{find}, @samp{xargs}, and @samp{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 @samp{find.exe}, you will need either to make sure DJGPP's
@file{bin} subdirectory is before the @file{C:@bs{}DOS} directory (for
DOS and Windows 3.X) and @file{C:@bs{}WINDOWS@bs{}COMMAND} directory
(for Windows 9X) on your @code{PATH}, or to rename the DOS @samp{find}
program to some other name.
@titem v2gnu/flx@value{flx-version}b.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.
@titem v2gnu/gwk@value{gawk-version}b.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.
@titem v2gnu/grep@value{grep-version}b.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.
@titem v2gnu/idu@value{idu-version}b.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 @samp{Grep}, but much faster, and
their notion of a token is sensitive to the source language of the
scanned file.
@titem v2gnu/pat@value{pat-version}b.zip
GNU Patch program and docs. Required to apply patches to sources given
a source-level patch-file generated by @samp{diff}.
@titem v2gnu/perl@value{perl-version}b.zip
Perl, a powerful scripting and text-processing language implemented as
an interpreter. Many sophisticated scripts, like
@code{texi2html}@footnote{
Like its name suggests, @code{texi2html} converts a Texinfo source to
HTML.}, use Perl.
@titem v2gnu/sed@value{sed-version}b.zip
GNU Sed (a batch editor) program and its docs. Many ported packages
require it during the build process on MSDOS.
@titem v2gnu/shl@value{shl-version}b.zip
GNU Sh-utils. A must if you use the port of @samp{bash} or want to run
Unix Makefiles, but some utilities (such as @samp{env} or @samp{test})
can also be very useful on their own right.
@titem v2gnu/txt@value{txt-version}b.zip
GNU Textutils. Includes many useful programs, such as @samp{sort},
@samp{wc}, @samp{cat}, @samp{join}, @samp{paste}, @samp{od}, and
@samp{uniq}. Unix shell scripts and Makefiles call some of these
@emph{a lot}, so you should install this package if you run them.
@end table
@paragraph{}
@item
Developing text-mode and graphics GUI applications:
@paragraph{}
@cindex Printing graphics, using GRX
@cindex Graphics print-out, using GRX
@table @file
@titem v2tk/grx@value{grx-version}.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 @file{addons/print} directory in the GRX distribution).
A significant drawback of GRX is that its docs is @emph{very} outdated
and incomplete.
@mail{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).
@titem v2tk/bcc2grx.zip
The interface library to convert Borland graphics calls into calls to
GRX library functions.
@titem v2tk/alleg@value{alleg-version}.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 @emph{not} under LGPL, it is free. A port of Allegro to
Win32 and to Linux is in the works (initial versions are available).
@cindex Allegro, home page and mailing list
By popular demand, Allegro now has its mailing list. To post a message
to the list, send email to @email{allegro@@canvaslink.com}. To
subscribe, send a message to @email{listserv@@canvaslink.com} with the
text ``subscribe allegro @{your full name@}''. Another related resource
is the @www{Allegro home page, www.talula.demon.co.uk/allegro/}.
@titem v2tk/pdc@value{pdc-version}.zip
@cindex Curses library for DJGPP
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
@ftp{via FTP, ftp.lightlink.com/pub/hessling/PDCurses/}.
@end table
@paragraph{}
@c @item
@c Fortran to C converter:
@c @paragraph{}
@c @table @file
@c @titem f2c@value{f2c-version}.zip
@c The djgpp port of the f2c converter and its support libraries.
@c @end table
@end itemize
Note that all of the packages have source distributions
(@file{...s.zip}) which you can download in case you discover a bug, or
want to know more about how the tools work.
@paragraph{}
For description of additional files not mentioned here, get the file
@file{00_index.txt}; it contains a full list of the distribution files and a
short description of every file.
@end itemize
@node Disk space, DJGPP Fatware, What to download, Getting DJGPP
@comment node-name, next, previous, up
@section How much disk space will I need?
@cindex Files, required disk space
@cindex Packages, required disk space
@cindex Memory size reported by go32-v2
@pindex go32-v2 reports the amount of memory and swap space
@quest{Wow, that's a lot of files. How much disk storage will I need?}
@ans{} The following lists the approximate disk space required for
several major configurations, and additional storage required for some
optional packages:
@ifclear html
@multitable {Additional storage for Graphics libraries} {300 KBytes}
@item Execution-only environment @tab 300 KBytes
@item Developing C programs @tab 15 MBytes
@item Developing C++ programs @tab 20 MBytes
@item Developing Objective-C programs @tab 16 MBytes
@item Additional storage for RHIDE @tab 4 MBytes
@item Additional storage for DJGPP sources @tab 6 MBytes
@item Additional storage for GDB @tab 1.1 MBytes
@item Additional storage for Emacs @tab 30 MBytes
@item Additional storage for Flex @tab 280 KBytes
@item Additional storage for Bison @tab 310 KBytes
@item Additional storage for Diffutils @tab 560 KBytes
@item Additional storage for Make @tab 650 KBytes
@item Additional storage for Patch @tab 180 KBytes
@item Additional storage for Sed @tab 200 KBytes
@item Additional storage for Graphics libraries @tab 4 MBytes
@end multitable
@end ifclear
@ifset html
@display
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
@end display
@end ifset
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.
@paragraph{}
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 @file{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 @ref{How much memory,
how to set up memory, How much virtual memory do you have}, below.
@node DJGPP Fatware, Uninstall, Disk space, Getting DJGPP
@comment node-name, next, previous, up
@section Can I get away with less megabytes?
@cindex Disk space, using less of it
@cindex FTP, downloading DJGPP in batch mode
@c @pindex EZ-GCC, a minimal DJGPP development environment
@c @cindex Minimal DJGPP development environment
@c @cindex Development environment, minimal
@cindex Automated downloading from a PC
@cindex Automated downloading from a Unix box
@cindex Automated FTP from a Unix box
@pindex BatchFTP, automated downloading from a Unix box
@quest{The above table means that I need more than 17 MBytes for C/C@t{++}
development environment; that's about 7 1.44MB diskettes to hold even
the compressed archive!! Seems to me DJGPP is afflicted by the
@strong{fatware} disease@dots{}}
@quest{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?}
@c @ans{} A minimal installation called @samp{EZ-GCC}, courtesy of
@c @mail{Anton Helm, tony@@nt.tuwien.ac.at}, is available by a WWW or
@c anonymous ftp. If you have WWW access, please start with the
@c @www{EZ-GCC Info Page, dictator/nt.tuwien.ac.at/ezgcc/} and get all
@c further info from there. All others can obtain @ftpusr{EZ-GCC from
@c Charles Sandmann's server, riceng.rice.edu, ezgcc, ezgcc}; please start by
@c downloading and reading the file @file{EZ-GCC.TXT} first.
@c @paragraph{}
@c This minimal installation requires only 3 1.44MB diskettes for fully
@c functional C/C++ development environment (including an editor), and an
@c additional one each for GDB, a full set of LIBGRX fonts, and Objective C.
@c @paragraph{}
@ans{} 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 @ftp{2M,
@SimTel{}/pub/simtelnet/msdos/diskutil/2m30.zip}.
@paragraph{}
To make downloading DJGPP easier, download and compile the
@samp{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
@samp{login refused} etc.) and also is nice to the remote server by
sleeping for some time between login attempts. @samp{BatchFTP} is free
software and can be found on @ftp{many FTP sites,
oak.oakland.edu/pub/unix-c/networks/batchftp.tar.Z}.
@paragraph{}
@samp{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.
@paragraph{}
As for the minimal DJGPP installation, volunteers are welcome to
prepare such an archive and make it publicly available, in the same
spirit as @samp{EZ-GCC} did for DJGPP v1.x.
@node Uninstall, , DJGPP Fatware, Getting DJGPP
@comment node-name, next, previous, up
@section How to uninstall a DJGPP package.
@cindex Uninstalling a package
@cindex Deleting a package
@cindex Removing a package
@quest{How can I uninstall a certain package?}
@quest{How can I install a newer version of some package without leaving
traces of the older installation?}
@ans{} The @file{*.mft} files in the @file{manifest} subdirectory hold
the lists of all the files included in every package you install. For
example, when you unzip @file{gcc281b.zip}, it puts a file called
@file{gcc281b.mft} into the @file{manifest} subdirectory. The easiest
way to remove all those files is to use the @file{*.mft} files as
response files to a command which deletes files. For example:
@example
rm -f @@manifest/gcc281b.mft
@end example
@noindent
The @code{rm} program is part of the GNU Fileutils package, available as
@file{v2gnu/fil@value{fil-version}b.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.
@node Docs, Trouble, Getting DJGPP, Top
@comment node-name, next, previous, up
@chapter The DJGPP Documentation
@cindex DJGPP Documentation
This chapter explains where to find and how to read DJGPP documentation,
and how to solve occasional problems with the docs system.
@menu
* Where is the docs:: Where to find the docs and how to read them.
* No Info:: For those who can't stand Info.
* Printed docs:: Where to find a printed manual.
* Cannot find docs:: For some programs it's tricky @dots{}
* Man pages:: How to read these.
* Last resort:: Look in the source, of course!
@end menu
@node Where is the docs, No Info, Docs, Docs
@comment node-name, next, previous, up
@section Where are the documentation files?
@cindex DJGPP documentation, where to find it
@cindex Getting documentation
@cindex Reading documentation
@cindex Browsing documentation
@cindex Documentation, reading
@pindex Info, a stand-alone docs browser
@pindex Emacs, reading Info files
@pindex Emacs, reading docs
@pindex RHIDE, reading docs
@pindex TkInfo, a Win32 tool to read Info files
@quest{I don't see any documentation files@dots{}}
@ans{} The documentation files are in the @file{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:
@enumerate a
@item
Use the stand-alone @samp{Info} reader.
@paragraph{}
@ftp{Texinfo,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2gnu/txi@value{txi-version}b.zip}
includes @file{INFO.EXE} and its docs. Unzip it and type @kbd{info
@key{Enter}}. It will bring up a (hopefully) self-explanatory online
help system. Confused? Press @kbd{?} to see the list of all Info
commands. Still confused? Press @kbd{h} to have @samp{Info} take you
on a guided tour through its commands and features.
@paragraph{}
@item
Use the @samp{Info} command of your favorite editor.
@paragraph{}
If you use Emacs, you already know about @samp{Info.} (What's that? You
don't? Type @kbd{C-h @key{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.
@paragraph{}
@item
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 @www{from the Web, math-www.uni-paderborn.de/~axel/tkinfo/}.
@end enumerate
@node No Info, Printed docs, Where is the docs, Docs
@comment node-name, next, previous, up
@section How to read the docs without @samp{Info?}
@cindex DJGPP documentation, reading as ASCII file
@cindex Documentation, converting to plain ASCII
@cindex Reading documentation, converting to plain ASCII
@cindex Reading documentation with text editor/viewer
@cindex Reading documentation with a Web browser
@pindex Makeinfo, using to convert Info files to plain ASCII
@quest{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??}
@ans{} 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.
@paragraph{}
You can also produce pure ASCII files yourself, if you have their Texinfo
sources. These are usually called @file{*.txi} or @file{*.texi} and
should be included with the source distribution of every package. (You
can use the @www{DJGPP server's downloading services,
www.delorie.com/djgpp/dl/ofc/}, to download individual files.) To
produce an ASCII file @file{foo.txt} from the Texinfo file
@file{foo.txi}, invoke the @samp{Makeinfo} program like this:
@smallexample
makeinfo --no-split --no-headers --output=foo.txt foo.txi
@end smallexample
@samp{Makeinfo} is one of the programs which come with the @ftp{GNU
Texinfo distribution,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2gnu/txi@value{txi-version}b.zip}.
@paragraph{}
If you prefer reading the docs through the Web, point your Web browser
to the @www{docs page of the DJGPP Web site, www.delorie.com/gnu/docs/}.
@node Printed docs, Cannot find docs, No Info, Docs
@comment node-name, next, previous, up
@section How to print the docs?
@cindex DJGPP documentation, printing
@cindex Documentation, converting to PostScript format
@cindex PostScript documentation
@cindex Printing DJGPP documentation
@cindex Library docs, missing libc2.tex
@cindex Library docs, problems in generating printed version
@cindex libc2.tex, missing file
@cindex DJGPP documentation, in PostScript format
@cindex Documentation, in PostScript format
@cindex DJGPP documentation, reading with a Web browser
@cindex HTML format, DJGPP documentation
@pindex TeX, printing the docs
@pindex LaTeX, printing the docs
@pindex emTeX, printing the docs
@pindex TEXI2PS, converting docs to crude PostScript
@quest{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?}
@ans{} Most of the DJGPP packages already have their docs converted to a
printable format, look for the files named @file{*d.zip} at the same
place where you got the binary @file{*b.zip} distribution. For example,
the ready-to-print docs of GCC 2.8.1 should be in the
@file{v2gnu/gcc281d.zip} archive. These distributions include a
@file{.dvi} and a @file{.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 @file{.dvi} file in conjunction with a @dfn{DVI driver}
for your printer to produce a printed copy of the docs. A DVI driver is
a program that reads the @file{.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 @ftp{on SimTel.NET mirrors in the v2apps/tex directory,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2apps/tex/dvlj@value{dvilj-version}.zip}.
Drivers for DeskJet series are also available from there, in the
@file{dvdjNNb.zip} archive. For other devices, download and install the
Ghostscript interpreter which supports a lot of popular printers.
@paragraph{}
If some package doesn't have a ready @file{*d.zip} archive, you will
need to get and install a program called @TeX{} or its work-alike, like
em@TeX{}. A DJGPP port of @TeX{} is available @ftp{on SimTel.NET,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2apps/tex/TeX.README}. Install
@TeX{}, then run the @code{texi2dvi} shell script@footnote{ You will
need to install the port of Bash and some auxiliary utilities to be able
to run shell scripts; @code{texi2dvi} itself is part of the GNU Texinfo
distribution and comes with the @file{v2gnu/txiNNNb.zip} archive.} on
the docs' @emph{source} files (called @file{*.txi} or @file{*.texi})
which you get with the source distribution of every package you
download. @TeX{} produces a @file{.dvi} file which you can then print
using one of the available DVI drivers, as explained above. To convert
a @file{.dvi} file into PostScript, use the @samp{DVIPS} program; you
can find it as dvps@value{dvips-version}.zip on the above-mentioned
site, together with the @TeX{} port.
@paragraph{}
If @TeX{} won't run, check that you have the file @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.
@paragraph{}
If you'd like to produce printed docs of the library reference, @TeX{}
might complain that it cannot find a file named @file{libc2.tex}. This
file is generated from all the @file{*.txh} files in the DJGPP source
distribution (@file{djlsr@value{djgpp-version}.zip}). In order to build
this file, you need to install @file{djlsr@value{djgpp-version}.zip} and
the C@t{++} compiler, then go to the @file{src/libc} directory and type
this from the DOS command prompt:
@example
make -C ../mkdoc
make doc
@end example
If the above command fails due to unresolved externals, you will need to
edit the file @file{makefile} in the @file{mkdoc} directory. It has a
line which calls @file{ld} (the linker), where you should change
@samp{-lgcc -lc} into @samp{-lgcc -lc -lgcc}. Save @file{makefile} and
try the above commands again.
@paragraph{}
Note that some documentation files (notably, the one for GCC and Emacs)
will produce voluminous print-outs. @emph{You have been warned!}
@paragraph{}
DJGPP comes with a program called @samp{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.
@paragraph{}
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 @mail{the FSF, fsforder@@gnu.org} for
details.
@paragraph{}
For those who prefer reading docs with a Web browser, many GNU manuals
in @samp{HTML} (hypertext) format, suitable for reading with your Web
browser, can be viewed at the @www{DJGPP Web site,
www.delorie.com/gnu/docs/}. The @file{*d.zip} archives also include the
docs converted to @samp{HTML}, which you can browse locally on your
machine.
@node Cannot find docs, Man pages, Printed docs, Docs
@comment node-name, next, previous, up
@section Some docs are nowhere to be found@dots{}
@cindex DJGPP documentation, look in source distributions
@cindex Documentation, inside source distribution archives
@pindex Sed, documentation
@pindex Gprof, documentation
@quest{I looked in my @file{info/} subdirectory, but I can't find docs
for some of the utilities, like @sc{sed} or @sc{gprof}.}
@quest{STL, the C@t{++} Standard Template Library, seems to be
undocumented@dots{}}
@ans{} @sc{sed} and @sc{gprof} are documented in the latest GNU
releases, @file{v2gnu/sed@value{sed-version}b.zip} and
@file{v2gnu/bnu@value{bnu-version}b.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 @www{on the net,
www.sgi.com/Technology/STL/}; this includes the full documentation and a
tutorial. Many books that describe C@t{++} programming also include
documentation of large parts of the STL.
If you have some other package without any docs, try downloading the
source archive (@file{*s.zip}) for that package and look inside it,
usually in the directory called @file{man/} or @file{doc/}. Omitting
documentation from the binary (@file{*b.zip}) distribution is generally
considered a bug, so if you find the docs in source distribution only,
please report these cases on @news{comp.os.msdos.djgpp}, so that next
binary release could fix this.
@node Man pages, Last resort, Cannot find docs, Docs
@comment node-name, next, previous, up
@section What are these @file{foo.1} files?
@cindex DJGPP documentation, in man page format
@cindex Documentation, in man page format
@cindex Man pages, how to read
@pindex Man program for DJGPP docs
@pindex Less, using to read man pages
@pindex More, using to read man pages
@pindex Groff, using to read man pages
@pindex Groff, port to DJGPP
@pindex Cawf, using to read man pages
@pindex Info, using to read man pages
@pindex Emacs, using to read man pages
@pindex Sed, using to convert formatted man pages to plain text
@quest{Some docs files are called @file{foo.1} or @file{bar.man} or
@file{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?}
@ans{} That weird format is the @samp{troff} format which is used for
writing Unix @dfn{manual pages}. The Unix command @samp{man} converts
them to formatted text files which are usually displayed with a program
like @samp{more} or @samp{less} (and here @samp{less} is considered to
be more than @samp{more} @b{:-)}). The formatted file includes bold and
underlined letters produced by over-typing using Backspace characters.
@paragraph{}
DJGPP binary @file{*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 @samp{man} command. One such
clone is available @ftp{from the DJGPP sites,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2apps/man12b.zip}.
@paragraph{}
@samp{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 @ftp{DJGPP port of GNU Less,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2gnu/lss@value{less-version}b.zip},
which uses colors to show bold and underlined letters.
@paragraph{}
Having installed @samp{man} and Less, you should be able to view
@file{*.1} files like e.g. @file{patch.1} with several alternative
tools:
@itemize @bullet{}
@item
Using the @samp{man} command itself: simply typing @kbd{man patch} from
the DOS prompt will cause @samp{man} to look for the man page
@file{patch.1} and pipe it to Less.
@paragraph{}
@item
Using the stand-alone Info reader: type @kbd{info patch}, and Info will
invoke @samp{man} as its back-end and display the manual page found by
@samp{man}.
@paragraph{}
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
@key{TAB} to move between the references and press @key{Enter} to
display the man page under cursor).
@paragraph{}
@item
Emacs, the GNU editor, can also display man pages. Type @kbd{M-x man
RET patch RET}, and Emacs will display the @samp{patch} man page
highlighted with colors. (You will need to install @sc{sed} and Gawk,
since Emacs invokes them when processing the man page.) Emacs also
supports the special sections like ``SEE ALSO''.
@end itemize
Note that all of these alternatives @emph{require} @samp{man} and Less
to be installed.
@paragraph{}
The binary distribution of the DJGPP port of @samp{bash} includes a
simple @sc{sed} script called @file{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:
@ifset html
@example
sed -f man2txt.sh < file.1 > file.txt
@end example
@end ifset
@ifclear html
@example
sed -f man2txt.sh < file.1 > file.txt
@end example
@end ifclear
If you want to be able to browse @emph{unformatted} man pages, get and
install the @ftp{DJGPP port of Groff,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2gnu/gro@value{gro-version}b.zip}.
@samp{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.
@paragraph{}
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.
@node Last resort, , Man pages, Docs
@comment node-name, next, previous, up
@section What if the docs don't say enough?
@cindex DJGPP documentation, see source files
@cindex Source files, using as the best docs
@quest{OK, I've got the docs and have read them, but I still can't figure
out some details.}
@ans{} Some ported packages include DJGPP-specific or MSDOS-specific
@file{README} files (named @file{README.dj}, @file{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.
@node Trouble, Compiler performance, Docs, Top
@comment node-name, next, previous, up
@chapter When the Compiler (or @samp{Make}, or @samp{Info}, or @dots{}) Crashes@dots{}
@cindex DJGPP programs, problems with
@cindex Problems with DJGPP programs
@cindex Crash, DJGPP programs
@cindex Hang, DJGPP programs
@cindex Reboot, when running DJGPP programs
This chapter explains how to deal with certain problems which may
prevent DJGPP programs from running on your machine. The first 12
@ifinfo
@ifset text
sections
@end ifset
@ifclear text
items on the next menu
@end ifclear
@end ifinfo
@iftex
sections
@end iftex
describe specific problems; if yours isn't solved with these techniques,
read
@ifinfo
the description of
@end ifinfo
@ref{General trouble, the general debugging procedure, Other kinds of
trouble}.
@menu
* Programs hang:: Some DJGPP programs hang.
* No DPMI:: You must have or install a DPMI server.
* Buggy DPMI:: It might crash all of your v2.x programs.
* GCC optimizations:: GCC sometimes crashes when optimizing.
* Missing subprograms:: GCC says @strong{``cannot exec as''}.
* Internal error:: GCC says @strong{``Internal compiler error''}.
* Unknown filetype:: GCC says @strong{``Unknown filetype''}.
* Make hangs:: Compiler hangs, but only under Make.
* Info cannot find Top:: Info won't display some files.
* Info crashes:: Info crashes upon startup.
* Bash crashes:: Possible reasons for Bash to crash.
* Linker accesses other drives::
* General trouble:: Look here for any problem not covered above.
* Redirect:: How to redirect GCC messages to a file.
* Deja vu:: Look up your problem in the DJGPP archives.
* Totally lost:: When nothing seems to help, ask on the net.
@end menu
@node Programs hang, No DPMI, Trouble, Trouble
@comment node-name, next, previous, up
@section GCC or some other DJGPP programs hang
@cindex DJGPP.ENV file causes GCC 2.8 to hang
@pindex Bash hangs on Windows 9X
@pindex Info hangs on Windows 9X
@pindex Less hangs on Windows 9X
@pindex RHIDE hangs on Windows 9X
@pindex Emacs hangs on Windows 9X
@quest{When I try to compile anything, GCC just hangs!}
@quest{Some programs, like Info and Less, hang on my Windows 9X machine
after some time, requiring to close the DOS box. Help!!}
@quest{Bash hangs on Windows 9X after the first DJGPP program I run from
it!}
@ans{} If you are using GCC 2.8.1, and if only GCC hangs, then chances
are that you have set the @code{DJGPP} environment variable incorrectly,
or didn't set it at all, or messed up your @file{DJGPP.ENV} file by
editing it. Refer to @ref{Missing headers or libraries, what to do if
GCC hangs, GCC cannot find headers or libraries}, later in this FAQ, for
details about possible problems with setting @code{DJGPP}. When
@code{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 @samp{NTDVM}
process on Windows/NT will go nuts allocating memory, as a result of
this).
@paragraph{}
The latest uploads of the GCC 2.8.1 binary (@file{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 @code{DJGPP} variable correctly.
@paragraph{}
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 @file{gnu/gcc-2.81/problems.txt}). In particular, GCC
2.8.1 comes with a modified version of @file{DJGPP.ENV} which you should
install over the stock version.
@paragraph{}
If interactive programs like Bash, Less, Info, Emacs, and @sc{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 @code{__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
@code{__dpmi_yield}.
@node No DPMI, Buggy DPMI, Programs hang, Trouble
@comment node-name, next, previous, up
@section GCC says ``No DPMI''
@cindex No DPMI error message
@cindex DJGPP won't run, prints ``No DPMI''
@cindex Load error---no DPMI
@quest{I'm trying to run @samp{gcc}, but all I get is a message saying
``Load error: no DPMI - Get csdpmi*.zip''. What am I doing wrong?}
@ans{} 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
(@file{v2misc/csdpmi@value{csdpmi-version}b.zip} from SimTel.NET
mirrors) which is a free DPMI server written for DJGPP.
@paragraph{}
If you already have CWSDPMI installed, and these messages still appear,
it might be because of a messed up @code{PATH} setting. The DJGPP
startup code looks for @file{cwsdpmi.exe} along the @code{PATH}, and,
being optimized for size, it might not be robust enough to cope with
all possible cases of weirdness in the value of @code{PATH}. Try to
copy @file{cwsdpmi.exe} into the same directory as the program you are
invoking, and if that helps, change your @code{PATH} as appropriate.
@paragraph{}
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
@file{autoexec.nt} file and remove the line which loads @file{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.
@node Buggy DPMI, GCC optimizations, No DPMI, Trouble
@comment node-name, next, previous, up
@section Buggy DPMI host or junk in DJGPP.ENV can crash v2.x programs
@cindex DJGPP programs, problems with DPMI host
@cindex DPMI host bugs, might crash DJGPP programs
@cindex Reboot, every DJGPP program
@cindex Hang, all DJGPP programs
@cindex Novell NDOS, buggy DPMI services crash DJGPP
@cindex Caldera OpenDOS, DPMI services crash DJGPP
@cindex DJGPP.ENV, trailing junk crashes Info
@pindex NWDOS, buggy DPMI services crash DJGPP
@pindex OpenDOS, bug in DPMI services crash DJGPP
@pindex QDPMI crashes Info and debuggers
@pindex Info crashes under QDPMI
@quest{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?}
@ans{} No, believe it or not, we don't want to oust you. Your problems
might be caused by a buggy @dfn{DPMI} (@pxref{DPMI Spec, DOS Protected
Mode Interface, Where to find the DPMI specification}) 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 @samp{DPMI=TRUE} parameter from the EMM386 command line, or
type @samp{DPMI OFF} from the DOS command prompt.
@paragraph{}
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
@samp{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.
@node GCC optimizations, Missing subprograms, Buggy DPMI, Trouble
@comment node-name, next, previous, up
@section GCC can crash during optimization
@cindex Optimization crashes GCC
@cindex Tracing compilation progress with -Q
@cindex Compilation progress, GCC switch
@cindex Virtual memory exhausted, during compilation
@cindex Compiling, on machines without a co-processor
@pindex GCC crashes during optimization
@pindex GCC exhausts virtual memory
@pindex PGCC exhausts virtual memory
@quest{When I compile my program, the compiler crashes, but the problem
seems to go away if I compile without optimization.}
@quest{The compiler prints ``Virtual memory exhausted'' and dies while
compiling some long functions with some optimization options, such as
-funroll-loops or -fforce-addr.}
@ans{} For some programs, this can be caused by an insufficient stack.
Some source files make @file{cc1.exe} or @file{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 @file{cc1.exe} was able to compile
it with optimizations!) Try stubediting the compiler to enlarge its
stack, as described elsewhere in this FAQ, @ref{Internal error, how to
enlarge the stack, What does ``Internal compiler error'' mean?}, before
you try any other remedies in this section.
@paragraph{}
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
@samp{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 @file{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
@samp{Memory}, as explained in @ref{Windows9X alloc, how to enlarge
memory in the DOS box, Memory allocation peculiarities under Windows
9X}.
@paragraph{}
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.
@paragraph{}
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@t{++} 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.
@paragraph{}
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 @file{emu387.dxe} file
from your @file{bin} subdirectory, when you compile on such machines,
and that your emulation-related setup is right. @xref{Emulation, how to
set up FP emulation, Floating-point code without 80387}, for details.
@paragraph{}
GCC can sometimes crash when optimizing, especially when compiling
C@t{++} 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 @code{#if 0 @dots{}
#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.
@paragraph{}
A GCC switch can sometimes help you zero in on the code fragment that
causes GCC to crash. If you add @samp{-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.
@paragraph{}
As an extreme measure, don't optimize at all, if that's the only way to
make your program compile.
@paragraph{}
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.
@paragraph{}
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 @ref{Internal error,
CWSDPMI allocation problems, What does ``Internal compiler error''
mean}, below.
@node Missing subprograms, Internal error, GCC optimizations, Trouble
@comment node-name, next, previous, up
@section Why does GCC say ``cannot exec @code{as}''?
@cindex GCC aborts with ``Installation problem, cannot exec as''
@cindex Cannot exec as, GCC message
@cindex GCC aborts with ``Installation problem, cannot exec cpp''
@cindex Cannot exec cpp, GCC message
@quest{When I try compiling a program, GCC aborts saying ``Installation
problem, cannot exec `as': No such file or directory (ENOENT)''. What
does that mean?}
@quest{When I try compiling a program, GCC aborts saying ``Installation
problem, cannot exec `cpp': No such file''. Huh?}
@ans{} This usually means that GCC couldn't find some program it needs
to run to compile your source. Check the @code{COMPILER_PATH}
environment variable or what the @code{COMPILER_PATH} line in the
@file{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: @file{cpp.exe}, @file{cc1.exe},
@file{cc1plus.exe}, @file{cxxfilt.exe}, @file{gasp.exe}, @file{as.exe},
@file{ld.exe}, and (for Objective-C) @file{cc1obj.exe.} A typical case
is when people fail to install the @ftp{Binutils package,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2gnu/bnu@value{bnu-version}b.zip} and
GCC cannot find @file{as.exe} (the assembler) and @file{ld.exe} (the
linker). You can use the @samp{-v} switch to GCC to see what programs
it invokes and which one of them causes the fatal error.
@paragraph{}
Beginning with version 2.8.0 of GCC, the place where the pre-processor,
@file{cpp.exe}, and the C and C@t{++} compilers, @file{cc1.exe} and
@file{cc1plus.exe}, are installed, has changed: they are no more in the
same directory as @file{gcc.exe} itself. If you are using GCC version
2.8.0 or later, and the compiler cannot find @file{cpp.exe}, read the
installation instructions carefully: the file @file{problems.txt}
explains how to change the settings on @file{DJGPP.ENV} so that GCC will
find the pre-processor.
@node Internal error, Unknown filetype, Missing subprograms, Trouble
@comment node-name, next, previous, up
@section What does ``Internal compiler error'' mean?
@cindex GCC aborts with ``Internal compiler error''
@cindex GCC says ``Abort!'' during compilation
@cindex Internal compiler error, when compiling C@t{++} programs
@cindex Abort! message during compilation
@cindex Environment variable DJGPP is not defined message
@cindex C compiler overflows its stack for large programs
@cindex C@t{++} compiler overflows its stack for large programs
@pindex GCC aborts or crashes during compilation
@pindex CWSDPMI runs out of virtual memory
@quest{During compilation, GCC prints ``Fatal: Error in DJGPP
installation. Environment variable DJGPP is not defined'' and then
aborts@dots{}}
@quest{GCC aborts with ``Internal compiler error'' when compiling a
large C@t{++} program.}
@quest{GCC behaves erratically when compiling programs, sometimes
crashes with register dump, sometimes compiles okay, sometimes reports
``Internal compiler error''. Why is this happening?}
@quest{When I try to compile any program, GCC prints ``Abort!'' and
doesn't compile anything@dots{}}
@quest{The compiler crashes or dies with ``Virtual memory exhausted''
when I compile my simple program!}
@cindex Environment variable DJGPP point to file which does not exist message
@cindex Environment variable DJGPP points to a wrong or corrupt file message
@ans{} The fatal error message about @code{DJGPP} not being defined
means just that---that your @code{DJGPP} environment variable is not
defined. The other two messages you could see are:
@display
@cartouche
Environment variable DJGPP point to file `XXYYZZ'
which doesn't exist
@end cartouche
@end display
@noindent
or
@display
@cartouche
Environment variable DJGPP points to wrong or corrupt file `ABCDEFG'
@end cartouche
@end display
@noindent
(In both cases, you will see an actual file name instead of
@code{XXYYZZ} and @code{ABCDEFG}.) These messages mean that
@code{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 @code{DJGPP} variable doesn't point to the actual path
name of a valid @file{DJGPP.ENV} file, because GCC uses the value of the
@code{DJGPP} variable to find out where to look for its subprograms like
@file{cpp.exe}, @file{cc1.exe}, etc. To solve this, set the
@code{DJGPP} variable as the installation instructions (in the file
@file{readme.1st}) describe. Also, make sure you didn't mess up the
beginning of the @file{DJGPP.ENV} file, where the value of the
@code{DJDIR} variable is computed (when in doubt, compare it with the
stock @file{DJGPP.ENV} from the @file{djdevNNN.zip} distribution).
@paragraph{}
A possible cause for the ``Abort!'' message is that the @code{TMPDIR}
environment variable points to a non-writable directory. If you don't
set @code{TMPDIR} from your @file{AUTOEXEC.BAT} or from the DOS prompt,
the DJGPP startup code sets it to the @file{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 @code{TMPDIR} to point to a writable
temporary directory. If @code{TMPDIR} is not set at all, GCC tries to
use @code{TEMP} and @code{TMP}, in that order, so make sure these also
point to a valid directory.
@paragraph{}
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 @ref{GCC
optimizations, use of the -Q switch, GCC can crash during
optimizations}, above. Once you find the offending code, you could
rewrite it and/or submit a bug report to the GCC maintainers.
@paragraph{}
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.
@paragraph{}
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.
@paragraph{}
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, @file{cc1.exe} or @file{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 @samp{stubedit} program,
like this:
@example
stubedit cc1.exe minstack=512k
@end example
I recommend to enlarge the maximum stack size of @file{cc1.exe} to at
least 512K bytes and that of @file{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@t{++} compiler to make such problems go away.
@paragraph{}
Note that the problems with insufficient stack size have nothing to do
with the total available memory as reported by @code{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.
@paragraph{}
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.
@paragraph{}
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 @code{sbrk}, by putting the following
somewhere in your program:
@example
@ifset html
#include <crt0.h>
@end ifset
@ifclear html
#include
@end ifclear
int _crt0_startup_flags = _CRT0_FLAG_UNIX_SBRK;
@end example
Note that the Unix algorithm for @code{sbrk} might cause trouble in
programs that install hardware interrupts handlers.
@node Unknown filetype, Make hangs, Internal error, Trouble
@comment node-name, next, previous, up
@section What does ``Unknown filetype'' mean?
@cindex Unknown filetype, GCC message
@cindex Mixing v2.0 GCC with CC1PLUS from v1.x
@cindex Virus infection cause ``Not COFF'' message
@cindex Not COFF error message from DJGPP programs
@pindex STUBIFY.EXE, infected by a virus
@quest{I get error messages saying ``Unknown filetype'' from GCC.}
@quest{Since a few days ago, whenever I try to run most of the DJGPP
programs, they print a message ``C:@bs{}DJGPP@bs{}BIN@bs{}prog.exe: not
COFF'' and just terminate. Help!!!}
@ans{} It might be that your DJGPP programs and/or @file{STUBIFY.EXE}
are infected by a virus. (This is @emph{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.
@paragraph{}
Another possible cause of the ``Unknown filetype'' message is that you
mix a v2.0 @file{gcc.exe} driver with @file{cc1plus.exe}, @file{cc1.exe}
or other programs from an old v1.x distribution.
@node Make hangs, Info cannot find Top, Unknown filetype, Trouble
@comment node-name, next, previous, up
@section Compiler hangs, but only when invoked from Make
@cindex GCC hangs/crashes under Make
@cindex Mixing v2.x Make with v1.x programs hangs the machine
@cindex Spawning v2.x programs from v1.x programs doesn't work
@cindex 16-bit DPMI programs cannot run under DJGPP
@cindex PATH, non-DJGPP binaries can crash GCC
@cindex Compiler, non-DJGPP, crashes under Make
@pindex GCC hangs under Make
@pindex Make, GCC hangs when invoked from it
@pindex GCC from v2.x crashes under v1.x Make
@quest{My compiles run OK from the command line, but hang or crash when
I invoke the compiler from Make.}
@quest{When I try to compile something, I get a message ``16-bit DPMI
not supported''.}
@ans{} Be sure you aren't inadvertently invoking some 16-bit programs,
such as Borland's Make or @file{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 @file{make.exe} or @file{cpp.exe} is found
earlier on your @code{PATH} than the Make and the preprocessor which
came with DJGPP. Moving DJGPP's @file{bin} directory to the beginning
of your @code{PATH} will usually solve these problems.
@paragraph{}
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
@file{cpp.exe} under GCC), the DOS box will usually crash. So this
problem is not specific to CWSDPMI.
@paragraph{}
If you @emph{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.
@paragraph{}
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
@samp{go32} to run it, but v1's @samp{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 @samp{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 @samp{go32-v2}
to work around this limitation (@pxref{go32-v2, description of go32-v2,
What is that @file{go32-v2.exe} program?}, below), but I suggest doing
that only if you absolutely cannot upgrade to v2's @samp{Make}.
@paragraph{}
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 @file{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.
@node Info cannot find Top, Info crashes, Make hangs, Trouble
@comment node-name, next, previous, up
@section Info doesn't like some files
@cindex Can't find node ``Top'', Info message
@cindex Info won't display a file
@cindex Info waits for 15 seconds
@cindex Info hangs for non-existent topics
@pindex Info won't display a file
@quest{When I run the Info browser, it tells me it cannot find the node
``Top''.}
@quest{Sometimes, when I mistype the name of the Info topic,
@file{info.exe} seems to hang@dots{}}
@ans{} Check your installation of info files. The file @file{DJGPP.ENV}
in the root of your DJGPP installation mentions the variable
@code{INFOPATH} which should point to the directory where Info looks for
its files. It must find there a file named @file{DIR}, the file you are
trying to read, and other files with @file{.iNN} or @file{.NN} extension,
where @file{NN} is a number. Also, make sure you didn't edit the
beginning of @file{DJGPP.ENV}, where the value of @code{%DJDIR%} is
computed; if you did, try the original @file{DJGPP.ENV}.
@paragraph{}
Also, the @code{DJGPP} environment variable should be set to point to
the full pathname of the file @file{DJGPP.ENV}. @xref{Missing
headers or libraries, problems with DJGPP variable setting, GCC cannot
find headers or libraries}, for a description of some frequent problems
with setting the @code{DJGPP} variable.
@paragraph{}
Assuming the above checks OK, and all the necessary info files are
indeed installed in those directories (did you remember to give that
@samp{-d} switch to @samp{PKUNZIP} when unzipping all DJGPP packages?),
it might be that you have an old version of @file{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.
@paragraph{}
Another possibility is that the file @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 @file{.gz} or similar extension that
tells @file{info.exe} to decompress it. You could examine the offending
file(s) with a text editor, and re-install them as needed.
@paragraph{}
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 @code{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.
@node Info crashes, Bash crashes, Info cannot find Top, Trouble
@comment node-name, next, previous, up
@section Info Crashes During Startup
@cindex Info viewer crashes at startup
@cindex ^Z character at end of DJGPP.ENV
@pindex Info crashes immediately upon startup
@pindex Info crashes due to ^Z or whitespace at end of DJGPP.ENV
@pindex EMM386 and DISPLAY.SYS, conflict with Info
@pindex DISPLAY.SYS and EMM386, conflict with Info
@pindex Info, conflicts with DISPLAY.SYS, EMM386
@quest{Whenever I invoke @file{info.exe}, it immediately crashes! How
can I use DJGPP without reading all those wonderful docs??}
@ans{} One possible reason for this is a bug in @code{EMM386} shipped
with some versions of DOS 6.x. This bug is only triggered if your
system loads the @code{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 @samp{[info]} section of @file{DJGPP.ENV}.) So
either switching to another display size, or removing either
@code{EMM386} or @code{DISPLAY.SYS} from @file{CONFIG.SYS}, should
prevent Info from crashing.
@paragraph{}
If you use DJGPP v2.0, yet another cause of crashes in @samp{Info} might
be trailing whitespace in the @file{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
@file{DJGPP.ENV} belongs to @samp{Info}, it is the one which suffers
most from this bug. Make sure your @file{DJGPP.ENV} doesn't have a
@kbd{^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.
@node Bash crashes, Linker accesses other drives, Info crashes, Trouble
@comment node-name, next, previous, up
@section Why does Bash crash?
@cindex /bin/sh in shell scripts
@cindex Shell scripts, failures and crashes
@cindex Pipe errors in shell scripts
@pindex Bash crashes
@quest{Bash crashes on me when I invoke shell scripts@dots{}}
@quest{Why does Bash say ``pipe error: Access denied'' when I try to run
two programs via a pipe?}
@quest{When I run certain complex shell scripts, Bash sometimes prints a
message saying ``Cannot make a child for command substitution:
(null)''. What gives??}
@ans{} If Bash crashes when you invoke shell scripts, check whether
those scripts have @samp{#!/bin/sh} on their first line. If they do,
the most probable reason for the crashes is that you don't have
@file{sh.exe} anywhere on your @code{PATH} (it does @emph{not} have to
be in @file{/bin}!). Either copy @file{bash.exe} into @file{sh.exe}, or
create a ``symlink'' to @file{bash.exe}, like this:
@example
ln -s c:/djgpp/bin/bash.exe c:/djgpp/bin/sh.exe
@end example
@noindent
(replace @samp{c:/djgpp} with the actual pathname of your DJGPP
installation).
@paragraph{}
Error messages about pipes and command substitution usually mean that
your @code{TMPDIR} environment variable points to an invalid drive. Old
ports of Bash had problems with @code{`command`} substitution, so make
sure you have the latest binaries.
@node Linker accesses other drives, General trouble, Bash crashes, Trouble
@comment node-name, next, previous, up
@section Why does the Linker Access my CD Drive?
@cindex Disks, accessed by the linker
@cindex Drives, accessed by the linker
@cindex Directories accessed by the linker
@cindex Linker, accesses random drives
@cindex Zip drive, accessed by the linker
@cindex CD-ROM, accessed by the linker
@quest{Why is it that every time I link a program, the CD-ROM drive is
accessed?}
@ans{} 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
@file{djgpp.djl} in a certain directory on the @file{D:} or @file{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 @file{bnuNNNb.zip} archive
you can find on SimTel.NET mirrors, and the problem should go away.
@paragraph{}
You can see which directories on what drives does the linker try to
access by passing the @samp{--verbose} option to the linker. Here's an
example:
@ifset html
@smallexample
gcc -o hello.exe hello.o -Xlinker --verbose > linker.log
@end smallexample
@end ifset
@ifclear html
@smallexample
gcc -o hello.exe hello.o -Xlinker --verbose > linker.log
@end smallexample
@end ifclear
@noindent
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.
@node General trouble, Redirect, Linker accesses other drives, Trouble
@comment node-name, next, previous, up
@section Other kinds of trouble
@cindex Programs crash, general troubleshooting
@cindex Crashes, general troubleshooting
@cindex Compiler crashes, which subprogram of
@cindex GCC crashes, which subprogram of
@pindex GCC crashes, which subprogram of
@quest{I've installed DJGPP just like explained in the @file{README.*}
files, but when I run gcc, my machine crashes/hangs/needs cold boot.}
@quest{I get errors I can't figure out when I try to compile something.}
@ans{} Add the @samp{-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.
@paragraph{}
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
@code{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 @ref{Config, system configuration advice, How to configure your
system for DJGPP}, earlier in this FAQ list, for other suggestions about
your system configuration.
@paragraph{}
Sometimes, if the @code{TMPDIR} environment variable points to a full
disk, GCC may hang or crash as well. Make sure you have enough free
disk space where @code{TMPDIR} points.
@node Redirect, Deja vu, General trouble, Trouble
@comment node-name, next, previous, up
@section I cannot keep up with the error messages
@cindex Programs crash, saving debugging output
@cindex Redirecting GCC messages to a file
@cindex Standard output/error stream, redirecting to a file
@cindex Error messages, redirecting to a file
@pindex GCC, redirecting messages to a file
@pindex 4DOS, redirecting GCC messages to a file
@pindex SCRIPT, redirecting GCC messages to a file
@pindex REDIR, redirecting GCC messages to a file
@quest{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?}
@quest{When I add @samp{-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?}
@quest{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?}
@ans{} Error messages are usually written to @code{stderr}, and stock
@file{COMMAND.COM} cannot redirect it. There are several alternatives
to do that:
@enumerate a
@item
You can use a shell smarter then @file{COMMAND.COM}, such as @samp{4DOS}
or @samp{bash}, which knows how to redirect standard error stream to a
file. 4DOS is shareware and can be found @ftp{on SimTel.NET,
@SimTel{}/pub/simtelnet/msdos/4dos/4dos601.zip}, while @samp{bash}
is available from the @file{v2gnu} directory of DJGPP archives
@ftp{on SimTel.NET,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2gnu/bsh@value{bsh-version}b.zip}.
@item
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 @samp{SCRIPT}, which is similar to its Unix namesake. It
has an advantage of saving everything which goes to screen @emph{and}
showing it on the screen at the same time. You can find @ftp{SCRIPT on
SimTel.NET, @SimTel{}/pub/simtelnet/msdos/screen/script11.zip}.
@item
Or you can use the @samp{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 @samp{REDIR}:
@example
redir -o gcc.log -eo gcc -v ...
@end example
(put the rest of the GCC command line instead of the dots). The
messages printed by GCC will be written to the file @file{gcc.log}.
@end enumerate
@node Deja vu, Totally lost, Redirect, Trouble
@comment node-name, next, previous, up
@section How to search DJGPP archives for similar problems
@cindex Programs crash, searching DJGPP archives
@cindex Solved problems, searching in DJGPP archives
@cindex Searching DJGPP archives
@cindex Problems, searching for solution in DJGPP archives
@cindex DJGPP archives, how to search
@cindex Archives, DJGPP mailing list/News group, how to search
@quest{OK, I have all this voluminous output of @samp{gcc -v}, but I
still have no clue.}
@ans{} Your problem might be one which has already been posted and
solved on the DJGPP News group. @DJ has set up a searchable News group
archive on @www{his Web server, www.delorie.com/djgpp/mail-archives/}.
You can search the @emph{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.
@node Totally lost, , Deja vu, Trouble
@comment node-name, next, previous, up
@section How to ask DJGPP gurus for help
@cindex Problems, asking for help
@cindex Gurus, asking for help
@cindex DJGPP users, asking for help
@cindex Asking for help
@cindex Help, asking for
@quest{I've read this monstrously-large FAQ, searched the news group
archives, but didn't find anything helpful. I am totally lost.
@strong{Help!!!}}
@quest{I don't have time to download all these messages, not to mention
looking through them. Can't you DJGPP gurus help me?
@strong{Please??}}
@ans{} 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:
@itemize @bullet{}
@item
At the DOS command prompt, type @kbd{set > environ.lst}, then press
@key{Enter}.
@item
Invoke the @samp{go32-v2} program (it's in your @file{bin/}
subdirectory) and save its output.
@item
Post to @news{comp.os.msdos.djgpp} or send electronic mail to the
@mail{DJGPP mailing list, djgpp@@delorie.com} and put into your message
the description of your calamity, the contents of the file
@file{ENVIRON.LST}, the output of @samp{go32-v2}, the contents of your
@file{AUTOEXEC.BAT} and @file{CONFIG.SYS}, and what GCC printed during
compilation with the @samp{-v} switch (if your problem is that GCC won't
work).
@item
If your problem involves a program that crashes and prints a stack dump,
please post that stack dump in its entirety; do @strong{not} omit any
details from the crash dump. It's best to run @code{symify} on the
stack dump, and post the output of @code{symify}:
@example
symify -o dumpfile yourprog
@end example
(@xref{Crash traceback, detailed description of symify, What is that
gibberish printed when my program crashes?}, for more details.
@paragraph{}
@item
Allow for 2-3 days (more on weekends) for all the reply messages to come
in, then act according to what they recommend.
@end itemize
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.
@node Compiler performance, Compiling, Trouble, Top
@comment node-name, next, previous, up
@chapter Compiler and Linker Performance
@cindex Compiler speed
@cindex Linker speed
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 @samp{-v} to your GCC
command line and run it again. With the @samp{-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.
@menu
* Slow compiler:: Are your compiles slow?
* Slow linker:: How to boost the linking speed.
@end menu
@node Slow compiler, Slow linker, Compiler performance, Compiler performance
@comment node-name, next, previous, up
@section Slow Compilation
@cindex Compilation speed
@cindex Speed of compilation
@cindex Slow compilation
@cindex BIOS setup, influence on compilation speed
@cindex Disk cache, influence on compilation speed
@cindex RAM disk, influence on compilation speed
@cindex Disabling virtual memory for CWSDPMI
@cindex Virtual memory, how to disable it for CWSDPMI
@pindex GCC, slow compilation
@pindex CWSDPMI, disabling virtual memory
@quest{Why GCC is compiling sooo slooowww?}
@ans{} 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:
@ifclear html
@multitable {Source language} {Without optimizations} {With -O2}
@item Source language @tab Without optimizations @tab With -O2
@item C@t{++} @tab 800 @tab 400
@item C @tab 1800 @tab 1000
@end multitable
@end ifclear
@ifset html
@example
| Without optimization | With -O2
-----------+------------------------+------------
C++ source | 800 | 400
-----------+------------------------+------------
C source | 1800 | 1000
@end example
@end ifset
@paragraph{}
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 @code{#include's} in the total line count. And
@strong{don't} check compilation speed on very short programs (like the
classic @samp{"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.
@paragraph{}
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 @emph{significantly} lower, you may indeed have a problem;
read on.
@paragraph{}
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 @samp{CWSDPMI}, load it
before your program with the @samp{-s-} switch, or use the
@samp{CWSPARAM} program to point the swap file to a non-existent drive),
or use or @samp{CWSDPR0} or @samp{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 @emph{was} paging in your
original environment.
@paragraph{}
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 (@pxref{Reasonable hardware, the description of
reasonable configuration, Machine most of us will @emph{actually} buy}).
Also see @ref{Config, recommendations for optimal software
configuration, How to configure your system for DJGPP?}.
@paragraph{}
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 @samp{SmartDrv} disk cache, this is
achieved by specifying @samp{/N/F} switches instead of @samp{/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.
@paragraph{}
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:
@ifclear html
@multitable {Internal and external CPU cache} {vendor-recommended optimal values}
@item Internal and external CPU cache @tab set to Enable
@item CPU cache scheme @tab set to Write-back, if possible
@item DRAM and SRAM wait states @tab vendor-recommended optimal values
@end multitable
@end ifclear
@ifset html
@display
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
@end display
@end ifset
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.
@node Slow linker, , Slow compiler, Compiler performance
@comment node-name, next, previous, up
@section Slow Linking
@cindex Linking speed, improve by stub-editing ld.exe
@cindex Network installation makes linking slow
@cindex Slow linking, possible reasons
@pindex ld, how to improve linking speed
@quest{The compiler finishes in a few seconds, but then the linker
grinds away for more than a minute, even on a very short program@dots{}}
@ans{} Try linking the trivial @samp{"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.
@paragraph{}
A few users have reported that they got much faster linking after
they've stub-edited @file{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 @code{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
@code{stdio} functions, whereby the size of the buffer for each
@code{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 @file{ld.exe}
and other similar programs.)
@paragraph{}
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 @samp{SmartDrv} disk cache, this is
achieved by specifying @samp{/N/F} switches instead of @samp{/X}.
@paragraph{}
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.
@paragraph{}
Another reason for slow linking might be that the @file{DJGPP.ENV} file
by default sets @code{TMPDIR} to a @file{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 @code{TMPDIR} to a directory on your local drive, or
to a RAM disk, would probably make linking faster.
@paragraph{}
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.
@node Compiling, Running, Compiler performance, Top
@comment node-name, next, previous, up
@chapter Compile-time and Link-time Problems
@cindex Compile-time problems
@cindex 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.
@paragraph{}
This chapter explains how to solve some of those problems which tend to
appear when compiling and linking your programs.
@menu
* Missing headers or libraries:: GCC can't find header files/libraries.
* Missing C++ headers:: GCC can't find C@t{++} header files.
* C++ comments:: Avoid C@t{++} comments in C programs.
* Which language:: GCC resolves it by looking at filename
extensions.
* Objective C:: Can't use ObjC 2.6.0.
* DJGPP-specific:: How to write DJGPP-specific fragments.
* Unresolved externals:: Where are those library functions?
* Which library:: Which library has which functions?
* Libraries order:: Which libraries to put first?
* Still unresolved:: C@t{++} misses complex and iostream functions.
* djgpp_first_ctor:: Why are these unresolved?
* Large image:: Static arrays bloat C@t{++} program image.
* Large executable:: Why is DJGPP .EXE so large?
* Linker script:: Problems with it can cause linker to fail.
* No EXE:: Novell Netware fails STUBIFY.
* Large object files:: Linker fails for large objects/libraries.
* Allegro:: Problems building Allegro library.
* NULL redefined:: Some C@t{++} headers redefine NULL.
* C++ exceptions:: GCC before 2.8.1 doesn't support them.
* Assembly output:: How to generate assembly code with GCC.
* movedata.h:: This header triggers compiler errors.
* Libraries:: How to create object libraries.
@end menu
@node Missing headers or libraries, Missing C++ headers, Compiling, Compiling
@comment node-name, next, previous, up
@section GCC can't find headers or libraries
@cindex Header files, GCC can't find
@cindex Libraries, GCC can't find
@cindex crt0.o, GCC can't find
@cindex Missing header files
@cindex Missing libraries
@cindex Missing crt0.o
@cindex Linker fails to find crt0.o under Novell
@cindex DJGPP environment variable, how to set and test
@cindex Long filenames in setting DJGPP env. variable
@cindex DJGPP environment variable, setting under LFN
@cindex DJGPP.ENV syntax explained
@pindex GCC can't find headers
@pindex GCC can't find libraries
@pindex GCC can't find crt0.o
@pindex GCC, environment variables
@pindex DJGPP.ENV syntax explained
@pindex DJGPP.ENV, compiler environment variables
@pindex DJGPP.ENV, beware of blanks when setting
@pindex Novell 3.X, linker doesn't find crt0.o
@pindex Windows 9X, setting DJGPP environment variable
@pindex WindowsNT, setting DJGPP environment variable
@quest{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?}
@quest{When I link my programs, ld.exe complains that it cannot open
crt0.o, although that file exists in the lib subdirectory@dots{}}
@quest{I tried to compile a program, but GCC complained about missing
header files @file{netdb.h} and @file{socket.h}. Can somebody please
mail me those headers?}
@quest{Why does GCC complain that it ``cannot open -lgcc: File format
not recognized''?}
@ans{} 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 @file{include} directory and its subdirectories; for C@t{++}
header files, look in the @file{lang/cxx} directory and its
subdirectories; for libraries look in the @file{lib} directory. Some
header files and object files which are specific to a certain GCC
version install into the @file{lib/gcc-lib/djgpp/X.YZ} directory (where
@file{X.YZ} is the GCC version number, e.g. 2.81), so look there as
well.
@paragraph{}
If a header file indeed is not there, and you cannot find it in the
@file{djdevNNN.zip} and @file{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 @file{socket.h} is not enough: you need the
library of the functions whose declarations and prototypes are in the
header.
@paragraph{}
If the header or the library @emph{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@footnote{
The example uses Unix-style forward slashes, but DOS-style backslashes
can also be used.}:
@example
set DJGPP=c:/djgpp/djgpp.env
@end example
@noindent
and it should point to the correct path of the file @file{DJGPP.ENV} on
your system; the file itself is in
@ftp{djdev@value{djgpp-version}.zip,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2/djdev@value{djgpp-version}.zip}
in the DJGPP distribution. In the above example it is assumed to be in
the @file{C:/DJGPP} directory, but you should set it as appropriate for
your installation.
@paragraph{}
Most of the problems with ``missing'' files, including the
highly-confusing message about @samp{-lgcc} (``File format not
recognized''), are usually caused by having the @code{DJGPP} variable
set incorrectly. The following describes some problems with defining
@code{DJGPP} which pop up frequently on the DJGPP forum.
@paragraph{}
Sometimes, people make errors in their @file{AUTOEXEC.BAT} that cause
the @var{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:
@example
set > env.lst
@end example
then examine the contents of the file @file{env.lst}. You should see
there a line like this:
@example
DJGPP=c:/djgpp/djgpp.env
@end example
If a line such as this isn't there, you should investigate the cause
for this (see below for some of the possibilities).
@paragraph{}
Many problems with setting @var{DJGPP} happen when people put excess
blanks around the @kbd{=} 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.
@paragraph{}
Another possible cause of @var{DJGPP} variable not being set is that you
invoke another batch file from your @file{AUTOEXEC.BAT} before the line
that sets @var{DJGPP}. Make sure such batch files are invoked with the
@code{CALL} statement, because otherwise the subsidiary batch file will
never return to process the rest of @file{AUTOEXEC.BAT} (that's a
``feature'' of DOS batch file processing).
@paragraph{}
The code that processes @file{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. @emph{Do NOT move DJGPP.ENV
to any other directory!}
@paragraph{}
Note that if you run DJGPP on Windows/NT, you @strong{cannot} use long
names of the directories in the pathname of @file{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
@file{DJGPP.ENV} file using its long pathname. For example, the
following setting @strong{won't work} on Windows/NT because
@file{Development} is longer than 8 characters:
@example
set DJGPP=c:/Programs/Development/Djgpp/djgpp.env
@end example
If the DJGPP variable is set correctly, then check the following possible
causes of this misbehavior:
@itemize @bullet{}
@item
You have edited the file @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 @file{DJGPP.ENV} before you edit it. The
DJGPP server has a page with a @www{description of the @file{DJGPP.ENV}
syntax, www.delorie.com/djgpp/doc/kb/kb_7.html#SEC7}
The syntax of @file{DJGPP.ENV} is also described in the @cite{DJGPP
Knowledge Base},
@ifinfo
@ifclear html
see @ref{(kb.inf)DJGPP.ENV, DJGPP.ENV section in the kb.inf file, },
@end ifclear
@end ifinfo
which comes with the @samp{djdev} distribution.
@item
Some older versions of Novell Netware cause the linker to fail if
the libraries or the startup file @file{crt0.o} reside on a networked
drive. This is due to a peculiarity of Novell that happens to fail the
library function @code{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 @samp{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.
@item
You renamed the @file{gcc.exe} driver to some other name. In this case,
you should edit the file @file{DJGPP.ENV} to add a section named after
the new name of GCC, which is an exact duplicate of the section called
@samp{[gcc]}. DJGPP start-up code uses this file to find environment
variables which it should put into the environment before the @code{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.
@item
Your @samp{FILES=} setting in @file{CONFIG.SYS} is insufficient, so GCC
runs out of available handles.
You should have at least @samp{FILE=15} in your @file{CONFIG.SYS}, more
on Windows. @xref{File handles, details about FILES= directive, How
many file handles can DJGPP use?}.
@item
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.
@item
You passed the @samp{-B} switch to GCC. This overrides the default
location of @file{crt0.o} and if you follow @samp{-B} with a directory
other than that where @file{crt0.o} resides, the linker won't find it.
You should not need to use the @samp{-B} or @samp{-L} switches at all if
your installation is correct and the @code{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
@samp{-L} or @samp{-B}, check out above for the possible causes.
@end itemize
@node Missing C++ headers, C++ comments, Missing headers or libraries, Compiling
@comment node-name, next, previous, up
@section GCC can't find C@t{++} headers
@cindex Header files, C@t{++}, GCC can't find
@cindex Missing C@t{++} header files
@cindex C@t{++}, missing header files
@cindex iostream.h, GCC can't find
@cindex String.h, GCC can't find
@cindex Regex.h, GCC can't find
@cindex Complex.h, GCC can't find
@cindex stdiostream.h, GCC can't find
@cindex streambuf.h, GCC can't find
@cindex iostreamP.h, GCC can't find
@pindex GCC can't find C@t{++} headers
@pindex Windows 9X long filenames and C@t{++} headers
@quest{I installed all the packages, but GCC complains it can't find
@file{iostream.h}, @file{_string.h} and other C@t{++} headers. Where can I
find those header files?}
@quest{GCC complains about being unable to find @file{Complex.h},
@file{Regex.h} and other header files which start with a capital letter,
and I indeed don't see them in my @file{lang/cxx/} directory. Where are
they?}
@quest{My C@t{++} program needs header files whose filenames exceed the 8+3
DOS filename restrictions, like @file{stdiostream.h} and
@file{streambuf.h}, and GCC cannot find those files. How in the world
can I write portable C@t{++} programs??}
@ans{} All C@t{++} include files are packaged as part of the @ftp{GNU
C@t{++} compiler distribution zip file,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2gnu/gpp@value{gcc-version}b.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 @file{complex.h},
@file{regex.h} and the like under case-insensitive DOS. Change
@code{Complex.h} to @code{_Complex.h}, and @code{String.h} to
@code{_String.h} in your source, and GCC will find them. The same goes
for the header @code{iostreamP.h}---you should use @code{_iostreamP.h}
instead. If you don't have the underscore @kbd{_} on your keyboard, you
might find using @code{strclass.h} instead of @code{_String.h} easier.
@paragraph{}
Another possibility to handle header files like @code{Complex.h} in a
portable way is to pass the @samp{-remap} switch (supported by GCC 2.8.0
and later) to the pre-processor; see the @samp{cpp} docs and the
@file{README.DJGPP} file in the GCC distribution, for more info about
this feature.
@paragraph{}
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
@dfn{Long File Names} (a.k.a.@: LFN) support is disabled. DJGPP v2.01
comes with LFN disabled by default on the @file{DJGPP.ENV} file. To
enable it, set the environment variable @code{LFN} to @samp{y}, like
this:
@example
set LFN=y
@end example
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.
@paragraph{}
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
@ref{WindowsNT, LFN driver for NT, Will it work under WindowsNT?},
earlier in this FAQ.
@paragraph{}
Another possible cause for problems with C@t{++} include files is that your
source file has a @file{.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@t{++}. Rename your file to @file{.cc} or
@file{.cpp} extension, or call GCC with the @samp{-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 @ref{Which
language, list of language-specific suffixes, How does GCC recognize the
source language?}, elsewhere in this FAQ.
@node C++ comments, Which language, Missing C++ headers, Compiling
@comment node-name, next, previous, up
@section GCC barfs on C@t{++}-style comments in C programs
@cindex C@t{++}-style comments in C programs, GCC won't compile
@cindex Comments, C@t{++}-style in C programs
@cindex -ansi switch and C@t{++}-style comments in C programs
@cindex -traditional switch and C@t{++}-style comments in C programs
@pindex GCC won't compile C@t{++}-style comments in C programs
@quest{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.}
@ans{} 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
@samp{-ansi} or @samp{-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@t{++} program, then rename it to have a suffix which will cause gcc
to compile it as such (@pxref{Which language, list of language-specific
suffixes, How does GCC recognize the source language?}), or use @samp{-x
c++} switch. If it's a C program, but you want to compile it as C@t{++}
anyway, try @samp{-x c++}; it can help, but can also get you in more
trouble, because C@t{++} has its own rules. For example, the following
program will print 10 if compiled as a C program, but 5 if compiled as
C@t{++}@footnote{
While admittedly perverse, this little monstrosity was written with
the sole purpose of demonstrating that C and C@t{++} have quite different
semantics under certain circumstances.}:
@example
@ifset html
#include <stdio.h>
@end ifset
@ifclear html
#include
@end ifclear
int
main ()
@{
printf ("%d \n" 10 //*
/ 2 //*/
1
);
return 0;
@}
@end example
If you must have both @samp{-ansi} and C@t{++}-style comments, use
@samp{-lang-c-c++-comments} preprocessor switch. Gcc doesn't accept
the @samp{-lang-XXX} switches on its command line, so you will have to
use the @samp{-Wp} option, like this:
@example
gcc -c -Wp,-lang-c-c++-comments myprog.c
@end example
Alternatively, you can add @samp{-lang-c-c++-comments} to the @code{*cpp:}
section of your @file{lib/specs} file (but that will make it permanent).
@paragraph{}
Bottom line: until the future ANSI/ISO C standard includes this as part
of the C language, it's best to change those @code{//} comments to
C-style ones, if you really mean to write a C program. The following
@sc{sed} command will convert a C program with C@t{++}-style comments
into a valid C source, provided you don't have the string ``//'' in a
character string:
@ifset html
@smallexample
sed "s?//\(.*\)?/*\1 */?" file.c > newfile.c
@end smallexample
@end ifset
@ifclear html
@smallexample
sed "s?//\(.*\)?/*\1 */?" file.c > newfile.c
@end smallexample
@end ifclear
@sc{sed} can be found with the DJGPP archives on SimTel.NET, in the
@file{v2gnu} directory.
@node Which language, Objective C, C++ comments, Compiling
@comment node-name, next, previous, up
@section How does GCC recognize the source language?
@cindex GCC can't recognize file format
@cindex GCC can't recognize source language
@cindex File format not recognized by GCC
@cindex Letter case in filenames submitted to GCC
@cindex Compilation messages, bogus
@pindex GCC, file source language recognition
@pindex GCC doesn't recognize file format
@pindex GCC, @samp{-v} switch shows the compilation passes
@quest{I type @kbd{GCC PROG.CC} and GCC complains that it can't recognize
@file{PROG.CC}'s file format. How come a C@t{++} compiler doesn't recognize a
C@t{++} source??}
@quest{I type @kbd{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.}
@ans{} That's because you typed your source file extension in
@emph{UPPER} case. GCC is @emph{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:
@table @file
@ifclear html
@titem .cc
@end ifclear
@ifset html
@c @titemx .cc
@end ifset
@titemx .C
@titemx .cxx
@titeml .cpp
C@t{++} source (passed through cpp).
@titem .c
C source that must be passed through cpp first.
@titem .i
Raw C source (no cpp pass).
@titem .ii
Raw C@t{++} source (not to be preprocessed).
@titem .m
Objective-C source.
@titem .S
Assembler that must be passed through cpp first.
@titem .s
Raw assembler source (no cpp pass).
@end table
Any other file is passed to the linker, under the assumption that it's an
object file.
@paragraph{}
In the examples above, @file{PROG.C} is taken as a C@t{++} program, not a C
one, and @file{PROG.CC} is passed to the linker as if it were an object
file. You can see what GCC does by adding the @samp{-v} switch to the GCC
command line; if you see that it's invoking @file{cc1plus.exe} (the C@t{++}
compiler) instead of @file{cc1.exe} (the C compiler), or calling
@file{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 @samp{-v}, see @ref{Redirect, how to capture GCC output, I
cannot keep up with the error messages}, earlier in this FAQ.
@paragraph{}
You can override the default rules gcc uses to decide how each input
file should be treated, using the @samp{-x LANGUAGE} switch. For
instance, the command
@example
gcc -x c++ prog.c
@end example
compiles @file{prog.c} as C@t{++} source. @extrefx{Overall Options,
@w{-x LANGUAGE} switch description, gcc, The GNU C Compiler Manual,
www.delorie.com/gnu/docs/gcc-2.7.2.2/gcc_8.html#SEC11}, for more info on
@samp{-x} options.
@node Objective C, DJGPP-specific, Which language, Compiling
@comment node-name, next, previous, up
@section Problems with Objective C
@cindex Compiling Objective C sources
@cindex Objective C, compiling
@pindex Objective C, compilation problems
@quest{How do I tell gcc my .cc file is to be compiled as Objective-C
source?}
@quest{I compile an Objective-C program, but get unresolved symbols.}
@quest{I can't compile the Objective-C test program which came with DJGPP.}
@ans{} Give your sources the @file{.m} extension, or use
@w{@samp{-x objective-c}} switch to GCC, so it will @emph{know} you mean
to compile with @w{Objective C}.
@paragraph{}
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.
@node DJGPP-specific, Unresolved externals, Objective C, Compiling
@comment node-name, next, previous, up
@section Writing codes fragments which are specific to DJGPP
@cindex DJGPP-specific code
@cindex Code, DJGPP-specific
@cindex Pre-processor symbols, DJGPP-specific
@cindex __DJGPP__ pre-processor symbol
@cindex __DJGPP_MINOR__ pre-processor symbol
@cindex __GO32__ pre-processor symbol
@quest{I must put a DJGPP-specific code fragment into my program. What
symbol should I use in the @code{#ifdef} directive to make it only visible
under DJGPP?}
@ans{} Use @code{__DJGPP__}, like this:
@example
#ifdef __DJGPP__
... DJGPP-specific code ...
#else
... not seen under DJGPP ...
#endif
@end example
@code{__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:
@example
#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
@end example
If you need to distinguish between minor DJGPP revision numbers, use the
symbol @code{__DJGPP_MINOR__}. For example:
@smallexample
#if defined(__DJGPP__) && __DJGPP__ == 2 && __DJGPP_MINOR__ == 1
.... will work only in DJGPP v2.01 ....
#endif
@end smallexample
Another DJGPP-specific pre-processor symbol which DJGPP defines is
@code{__GO32__}; but it is only provided for compatibility with previous
versions of DJGPP (v1.x) and its use should be discouraged.
@node Unresolved externals, Which library, DJGPP-specific, Compiling
@comment node-name, next, previous, up
@section Unresolved externals when linking programs
@cindex Unresolved externals
@cindex Unresolved externals in C@t{++} programs, use GXX
@cindex Undefined references, when linking Flex programs
@cindex Linking programs, unresolved library functions
@cindex Linking C@t{++} programs, use the GXX driver
@cindex Libraries, optional, how to link
@cindex Library functions, linker won't find
@cindex Floating-point math functions, standard and high-quality
@cindex C@t{++} STL library, not in lgp271b distribution
@cindex STL library, not in lgp271b distribution
@cindex Linker cannot find -lstdcx
@cindex -lstdcx, linker cannot find
@cindex Linking Flex programs
@cindex Flex programs, linking
@cindex iostream library, why use it
@cindex obstack package
@cindex regex package from GNU
@cindex libgpp library
@cindex libg++ library
@cindex libstdc++ standard templates library
@cindex Math library, default ANSI/ISO and high-quality functions
@cindex Linking against optional libraries
@cindex Linker can't find library functions
@pindex gxx driver, searches C@t{++} libraries automatically
@pindex gxx driver, not in gcc272b distribution
@pindex Flex, undefined references
@quest{Why do I get so many unresolved symbols when linking my programs?}
@quest{Why does GCC complain that it cannot open -lstdcx?}
@quest{Why do I get ``Undefined reference to yywrap'' when linking
programs produced by Flex?}
@ans{} By default, GCC instructs the linker to only look in two
libraries: @file{libgcc.a} and @file{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 @file{libxy.a}, put the library into
the DJGPP @file{lib/} subdirectory and append a @samp{-lxy} to the link
command line. The Standard C@t{++} Template classes are in
@file{libstdcxx.a} (it's called @file{libstdc++.a} on Unix); append
@samp{-lstdcxx}. To use the additional GNU C@t{++} classes in the
@file{libgpp.a} library (it's called @file{libg++.a} on Unix systems),
append @samp{-lgpp}. Flex-generated lexical analyzers call functions in
the @file{libfl.a} library; you need to append @samp{-lfl} when linking
them.
@paragraph{}
When linking C@t{++} programs, you can use either one of the @samp{gxx},
@samp{gpp}, or @samp{g++} commands (the latter on Windows 9X only)
instead of @samp{gcc}; they will then instruct the linker to also scan
the C@t{++} libraries automatically, so you don't have to remember doing
that yourself.
@paragraph{}
Another reason for undefined references when linking C@t{++} programs is
that you mix GCC and @file{libstdcxx.a} from different releases: they
are usually incompatible.
@paragraph{}
An error message about missing @file{-lstdcx} usually means that the
linker cannot find the standard C@t{++} library, @file{libstdcxx.a}. Look
into your @file{lib/} subdirectory to see if it's there; if not, unzip
it from the @file{gppNNNb.zip} file. If @file{libstdcxx.a} exists but
the linker still complains, you most probably have a problem related to
long file names on Windows 9X (@file{libstdcxx.a} exceeds the DOS 8+3
limits). For a quick fix, try to @samp{set LFN=y} in the environment
and see if that helps. If that doesn't help, make sure you unpacked
@file{gppNNNb.zip} with an unzip program which supports long file names.
This issue is further complicated if you use @sc{rhide}, and is
described in full in the file @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
@file{rhide.env} or to @file{DJGPP.ENV} which says this:
@example
RHIDE_TYPED_LIBS_DJGPP.cc=stdcxx
@end example
When you add this line, make sure neither it nor the @samp{[rhide]} line
have trailing whitespace, otherwise @sc{rhide} will not recognize these
lines.
@paragraph{}
If your program uses a lot of floating-point math, or needs math
functions beyond those specified in the ANSI/ISO standard, consider
appending @kbd{-lm} to your link command line. The basic math functions
required by ANSI/ISO standard are included in the @file{libc.a} library,
but @file{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 @file{libm.a} always set
@code{errno}), a @code{matherr} facility, etc.
@node Which library, Libraries order, Unresolved externals, Compiling
@comment node-name, next, previous, up
@section How not to lose your head with all these libraries
@cindex Libraries, searching for functions
@cindex Functions, which is in what library
@pindex NM, printing library contents
@quest{I'm lost with all those different libraries. How in the world
can I find out which functions are included in which library?}
@ans{} You can use the @samp{nm} program to check what functions are
included in a library. Run it with the @samp{-C} option and with the library
as its argument and look in the output for the name of your function (the
@samp{-C}, or @samp{--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 @code{T} before their
name. For example, the following is a fragment from the listing produced by
@samp{nm}:
@example
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.
.
.
.
@end example
Here we see that the module @file{stdio.o} defines the functions
@code{clearerr}, @code{feof}, @code{ferror}, @code{fileno}, @code{getc},
@code{getchar}, @code{putc} and @code{putchar}, and calls functions
@code{_filbuf} and @code{_flsbuf} which aren't defined on this module.
@paragraph{}
Alternatively, you can call @samp{nm} with the @samp{-s} or
@samp{--print-armap}, which will print an index of what symbols are
included in what modules. For instance, for @file{libc.a}, we will see:
@example
c:\djgpp\lib> nm --print-armap libc.a
.
.
.
_feof in stdio.o
_ferror in stdio.o
_fileno in stdio.o
.
.
.
@end example
which tells us that the functions @code{feof}, @code{ferror} and
@code{fileno} are defined in the module @file{stdio.o.}
@paragraph{}
@samp{nm} is fully described in the GNU docs. @extrefx{nm, nm, binutils,
GNU Binutils Manual,
www.delorie.com/gnu/docs/binutils-2.7/binutils_6.html#SEC5}.
@node Libraries order, Still unresolved, Which library, Compiling
@comment node-name, next, previous, up
@section DJGPP uses a one-pass linker
@cindex Libraries, order on compilation/link command line
@cindex Linking programs, unresolved library functions, libraries' order
@cindex Library functions, linker won't find, libraries' order
@cindex Library functions, linker won't find in non-default directories
@cindex Environment variables, linker
@pindex Linker can't find library functions in non-default directories
@pindex Linker, order of libraries in the command line
@pindex DJGPP.ENV, linker environment variables
@pindex Linker, environment variables
@quest{I give all the libraries to gcc, but I still get unresolved
externals when I link. What gives?}
@ans{} @samp{Ld} is a one-pass linker: it only scans each library once
looking for unresolved externals it saw @emph{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
@emph{after} all the object files, and in this order:
@example
-lgpp -lstdcxx -lm
@end example
E.g., to link files main.o and sub.o into a C@t{++} library, use the following
command line:
@example
gcc -o main.exe main.o sub.o -lgpp -lstdcxx
@end example
or, if you compile and link in one command:
@example
gcc -o main.exe main.cc sub.cc -lgpp -lstdcxx -lm
@end example
If you have any libraries of your own, put them @emph{before} the above
system libraries, like this:
@example
gcc -o main.exe main.cc sub.cc -lmylib -lgpp -lstdcxx -lm
@end example
@pindex g++ compilation driver, alternative names on DOS
When you use the @samp{gxx}, the @samp{gpp} or @samp{g++} compilation
drivers to compile a C@t{++} program, it automatically names the C@t{++}
libraries in the correct order. (@samp{gpp} and @samp{gxx} are the
alternative names for @samp{g++} on DOS, which doesn't allow the
@samp{+} character in file names.)
@paragraph{}
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 @samp{-(} and the @samp{-)} options (if you invoke
GCC to link, use the @samp{-Wl} or @samp{-Xlinker} options to pass
switches to the linker). Check out the linker docs for more info about
@samp{-( ... -)} groups.
@paragraph{}
If your installation tree is different from the default, i.e., if you keep
the libraries @strong{not} in the default @file{lib/} subdirectory, then
you should add that directory to the line in the @samp{[gcc]} section of
your @file{DJGPP.ENV} file which starts with @samp{LIBRARY_PATH}, or put
into your environment a variable called @code{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
@code{LIBRARY_PATH} will have no effect, because this variable is only
known to the gcc driver. So if you must call @samp{ld} directly, use
the @samp{-L} option to tell it where to look for the libraries.
@node Still unresolved, djgpp_first_ctor, Libraries order, Compiling
@comment node-name, next, previous, up
@section Some functions still not found in C@t{++} programs
@cindex Unresolved externals, C@t{++}
@cindex Linking programs, unresolved C@t{++} library functions
@cindex Library functions, C@t{++}, linker won't find
@cindex Inline functions, linker won't find
@cindex C@t{++} libraries compiled with v2.8.0 don't mix with 2.8.1
@cindex libgcc.a, should be in sync with the compiler
@cindex extern "C" qualifier
@cindex Linking C functions with C@t{++} programs
@cindex C@t{++} programs, linking with C functions
@cindex Linker can't find some C@t{++} library functions
@cindex iostream functions, linker can't find
@cindex __throw and __eh_pc, undefined references
@cindex __eh_pc and __throw, undefined references
@cindex complex.h functions, linker can't find
@pindex GCC won't find inline functions without -O
@quest{I put all the libraries in the above order, but the linker still
can't find some C@t{++} functions from @file{complex.h} and
@file{iostream.h.}}
@quest{I get many undefined references to symbols like @code{__eh_pc},
@code{terminate}, and @code{__throw}@dots{}}
@ans{} Some C@t{++} functions are declared @code{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 @samp{-O}.
@paragraph{}
Another cause of missing external symbols might be that your versions of
@file{libgcc.a} and the compiler aren't in sync. These cases usually
produce undefined references to symbols such as @code{__throw} and
@code{__eh_pc}. You should only use @file{libgcc.a} from the same
distribution where you got the compiler binaries. The reason for these
problems is that the setup for supporting C@t{++} exceptions is subtly
different in each version of the compiler.
@paragraph{}
For C@t{++} 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@t{++} object files or libraries, try using
the @samp{-fno-exceptions -fno-rtti} switches to GCC, it helps
sometimes.
@paragraph{}
If you call C functions from a C@t{++} program, you need to make sure
the prototype of the C function is declared with the @code{extern "C"}
qualifier. DJGPP header files take care about this, but headers you get
with third-party libraries might not. Failure to use @code{extern "C"}
will cause the linker to look for a C@t{++} function instead of a C
function, which will fail because names of C@t{++} functions are mangled
by the compiler.
@node djgpp_first_ctor, Large image, Still unresolved, Compiling
@comment node-name, next, previous, up
@section Unresolved djgpp_first_ctor
@cindex djgpp_first_ctor, unresolved by linker
@cindex djgpp_first_dtor, unresolved by linker
@cindex Linker won't find djgpp_first_dtor symbol
@cindex Unresolved externals, djgpp_first_ctor
@pindex GCC cannot resolve djgpp_first_ctor symbol when linking
@pindex LD linker, linker script defines djgpp_first_ctor
@quest{I do everything like your praised FAQ says, but the linker
complains about unresolved symbols with strange names like
@samp{djgpp_first_ctor}, @samp{djgpp_last_dtor}, etc. I looked in every
library with @code{nm}, and I cannot find these creatures. Where in the
world are they??}
@ans{} These symbols are defined by the @file{djgpp.djl} linker script
that should be in your @file{lib/} subdirectory. When you call
@samp{gcc} to link a program, it invokes @file{ld.exe} with the option
@samp{-Tdjgpp.djl.} If you invoke @samp{ld} directly (this is generally
not recommended), be sure to include that switch. If you did invoke it
through @samp{gcc}, maybe your linker is set up incorrectly. Add
@samp{-v} to the GCC switches and check that the command line that GCC
gives to LD includes that switch, that your @file{lib/} subdirectory
includes that script file, and that the script file is intact and
includes the definition of the above symbols.
@paragraph{}
Another reason might be that you have edited your @file{DJGPP.ENV} file
in a way that prevents the linker from finding its @file{djgpp.djl} script.
@paragraph{}
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.
@node Large image, Large executable, djgpp_first_ctor, Compiling
@comment node-name, next, previous, up
@section C@t{++} programs yield large @file{.exe} file
@cindex C@t{++} programs, large executable
@cindex Static array enlarges C@t{++} executable
@cindex Executable, bloated by static array
@cindex -fconserve-space switch
@pindex GCC, -fconserve-space switch
@quest{It seems that declaring a large @code{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?}
@ans{} This only happens in C@t{++} programs and is a (mis-)feature of GCC.
You can use the @samp{-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 @samp{-fconserve-space} switch is
described in the GCC docs, @extref{C++ Dialect Options, -fconserve-space
Option, gcc, GNU C Compiler Manual,
www.delorie.com/gnu/docs/gcc-2.7.2.2/gcc_11.html#SEC14}.
@paragraph{}
If the problems with using this switch doesn't deter you, you can even
add this switch to your @file{lib/specs} file to make it permanent.
@node Large executable, Linker script, Large image, Compiling
@comment node-name, next, previous, up
@section Why are DJGPP @file{.exe} files so large?
@cindex Executable size, how to make smaller
@cindex Compressing DJGPP executables
@cindex EXE compressor for DJGPP
@cindex Debugging symbols, how to strip from executables
@cindex Executable, how to strip off debugging symbols
@pindex DJP, an executable compressor for DJGPP
@pindex DJP compressor supports DLM
@pindex STRIP makes executables smaller
@pindex DLM compression, with DJP
@quest{I compiled a trivial ``Hello world'' program and got a 80KB
executable file. That's ridiculously bloated!}
@quest{I switched to GCC 2.8.1, and my C@t{++} executables are considerably
larger than when compiled with GCC 2.7.2.1!}
@ans{} Did you link with @samp{-s} switch to @samp{gcc}, or run
@samp{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 @samp{-s} is not passed to gcc by default.)
@paragraph{}
C@t{++} 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 @file{bnuNNNb.zip}.
@paragraph{}
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.
@paragraph
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 @samp{go32} in v1.x), are now also part of the
startup code.
@paragraph{}
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 @code{__crt0_glob_function},
@code{__crt0_load_environment_file}, and @code{__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@footnote{
If you define an empty substitute for @code{__crt0_setup_arguments}, you
don't need to define a substitute for @code{__crt0_glob_function}.}:
@example
char **__crt0_glob_function (char *arg) @{ return 0; @}
void __crt0_load_environment_file (char *progname) @{ @}
void __crt0_setup_arguments (void) @{ @}
@end example
Note that if you define an empty substitute for
@code{__crt0_setup_arguments}, your program will not be able to access
its command-line arguments via the @code{argv[]} array. So this is only
recommended for programs which don't accept any arguments at all.
@paragraph{}
@pindex DJP, incompatibilities with Binutils
@pindex Binutils, incompatibilities with DJP
You can make your program image still smaller by compressing it with
a compressor called @ftp{@sc{djp},
@SimTel{}/pub/simtelnet/gnu/djgpp/v2misc/mlp107b.zip}. @sc{djp} is
a DJGPP-specific executable file compressor. It is fast and has no
memory overhead. It also knows about DJGPP @dfn{Dynamically Loaded
Modules} (DLM) technology. (Note that @sc{djp} before version 1.06 was
incompatible with Binutils 2.8.1 and later@footnote{
In particular, running @code{strip} on a program and then compressing it
with @sc{djp} would produce a program that crashes upon startup.}, so
you should always use the latest @sc{djp} version available on
SimTel.NET mirrors.)
@node Linker script, No EXE, Large executable, Compiling
@comment node-name, next, previous, up
@section Linker complains about @file{djgpp.lnk}
@cindex Linker fails because of Windows 9X shortcut files
@cindex Shortcut files under Windows 9X fail DJGPP linker
@pindex Windows 9X, shortcut files conflict with ld
@quest{I run DJGPP under Windows 9X, but the linker complains about
@file{djgpp.lnk} file@dots{}}
@ans{} 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
@code{djgpp}, Windows will create a file @file{djgpp.lnk} in your
working directory. In that case, when @file{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 @file{djgpp.djl}, so that this conflict doesn't
exist after you upgrade.
@node No EXE, Large object files, Linker script, Compiling
@comment node-name, next, previous, up
@section Linker fails to produce the EXE program under Novell
@cindex Linker fails to produce executable under Novell
@cindex Novell, linker or STUBIFY don't produce executable
@pindex STUBIFY fails to produce .EXE under Novell
@quest{When I link my program, it fails to produce the .EXE executable,
but only if I do this on a networked drive@dots{}}
@quest{I run STUBIFY on a networked drive under Novell, but it doesn't
produce a .EXE file. How come?}
@ans{} 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 @samp{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 @samp{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:
@enumerate
@item
You can remove the other files, rename them, or move them to another
directory that isn't searched by Novell.
@item
You can rename the program you are trying to link.
@item
You can change the way Novell searches for files (a.k.a.@: @dfn{the
search mode}), so that it won't look in the directories on your PATH.
@item
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.
@item
You can change the search mode for @samp{STUBIFY} and the linker (or for
any other program that gives you that trouble) by running commands like
these:
@example
SMODE stubify.exe 2
SMODE ld.exe 2
@end example
@end enumerate
@node Large object files, Allegro, No EXE, Compiling
@comment node-name, next, previous, up
@section Linker fails for large object files or large libraries
@cindex Linker fails for large libraries or object files
@cindex Linker fails for a.out files in a library
@cindex Linker fails for obj files converted by EMXAOUT
@pindex ld fails for large libraries and object files
@pindex ld fails for obj files converted by EMXAOUT
@pindex ld fails for a.out files in a library
@pindex POVRAY, linker fails to link the library
@quest{Whenever I define very large static arrays in my program, the
linker fails saying ``could not read symbols: Bad value''. Huh??}
@quest{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?}
@ans{} This is a known bug in @file{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 @file{ld.exe} exhibits such bugs, these
are your alternatives for a work-around:
@itemize @bullet{}
@item
In case of a large library, split it into several smaller ones.
@item
For a module that defines large data structures, move some of the static
data to other files, or allocate the space at runtime with
@code{calloc}.
@end itemize
@file{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 @samp{POVRAY}
package, where the failure is caused by an object file called
@file{_pmlite.o} in the @file{pmode.a} library. The problem here is
that @file{_pmlite.o} is a TASM-compiled file, processed by
@samp{EMXAOUT}. @samp{EMXAOUT} produces @samp{a.out} object files which
@file{ld.exe} cannot link if they are in a library. Either taking that
object file out of the library, or processing the original
@file{_pmlite.obj} with another tool (such as @samp{OBJ2BFD} or
@samp{OBJ2COFF}) will solve these problems. Note however, that the
authors of @samp{OBJ2COFF} have explicitly forbidden commercial use of
their tool.
@node Allegro, NULL redefined, Large object files, Compiling
@comment node-name, next, previous, up
@section Building Allegro library fails
@cindex Allegro library, failure to compile
@quest{When I try to build the Allegro library, liballeg.a, I get some
cryptic message about register-opcode mismatch. What am I doing wrong?}
@quest{It seems I miss one of the source files from the Allegro
distribution, because Make cannot find it when I try to build Allegro.}
@quest{I can't build Allegro: it keeps telling me that I ``need to
install gcc2721b.zip''. But I already have GCC installed!}
@ans{} You should get the latest version of Allegro that is available
@ftp{from SimTel.NET,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2tk/alleg@value{alleg-version}.zip}
or @www{from Shawn Hargreaves' site, www.talula.demon.co.uk/allegro/}.
Versions of Allegro before 3.0 are known to have bugs such as above.
@node NULL redefined, C++ exceptions, Allegro, Compiling
@comment node-name, next, previous, up
@section C@t{++} compiler says ``NULL redefined''
@cindex NULL, redefinition in C@t{++} header files
@cindex Redefinition of NULL in C@t{++} headers
@quest{When I compile a C@t{++} program which includes some standard C
header files, the compiler prints error messages about redefinition of
@code{NULL}@dots{}}
@ans{} This is because GCC 2.8.1 comes with C@t{++} header files which
redefine @code{NULL} in a way that conflicts with the DJGPP headers.
It's a bug in the GNU C@t{++} headers, but until it is fixed, you will
need to make sure you include the C@t{++} headers @emph{after} the C
headers. If that doesn't help in your case, you will need to hack your
headers to reconcile them.
@node C++ exceptions, Assembly output, NULL redefined, Compiling
@comment node-name, next, previous, up
@section C@t{++} exceptions support
@cindex Exceptions, C@t{++}, support by GCC
@cindex C@t{++} exceptions, support by GCC
@cindex Abort! message in C@t{++} programs that use exceptions
@cindex Exceptions, with -fsjlj-exceptions
@quest{I've written a program that uses C@t{++} exceptions, but instead of
catching an exception, the program prints ``Abort!'' and dies@dots{}}
@quest{When linking C@t{++} programs, I get messages about undefined
references to @code{__EH_FRAME_BEGIN__} and such likes. Huh?}
@quest{I cannot compile C@t{++} programs that include the header
@file{math.h}: the compiler complains about redefinition of class
exception!}
@ans{} C@t{++} exceptions were not fully supported in DJGPP before version
2.8.1 of GCC. Either upgrade to the latest version or compile with the
@samp{-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 @samp{-frtti} compiler switch and include the
@file{typeinfo} header in your program.
@paragraph{}
Note that exception support with @samp{-fsjlj-exceptions} is very slow,
since it has a significant runtime overhead, even if the exception
doesn't occur.
@paragraph{}
If you already use GCC 2.8.1, these problems could happen if you failed
to replace the @file{specs} file with the version which comes with the
GCC 2.8.1 distribution. Read the file @file{README.DJGPP} in the GCC
distribution, for more details.
@paragraph{}
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.
@paragraph{}
@cindex __EH_FRAME_BEGIN__, undefined references
@cindex Undefined references to __EH_FRAME_BEGIN__
Undefined references to symbols like @code{__EH_FRAME_BEGIN__} are a
symptom of using an old linker script @file{djgpp.djl}. You should
remove this file from your @file{lib} subdirectory, which lets GCC use
the new version that installs into the @file{lib/gcc-lib/djgpp/X.YZ/}
directory (where @file{X.YZ} is the GCC version number). Again,
@file{README.DJGPP} in the GCC distribution has more on this.
@paragraph{}
@cindex Redefinition of class exception, compiler message
@cindex math.h, conflicts with C@t{++} programs
If GCC complains about ``Redefinition of class exception'' when you
compile C@t{++} programs which include the header @file{math.h}, you
need to replace that header. GCC 2.8.1 comes with a header
@file{exception} that conflicts with @file{math.h} from DJGPP v2.01,
which defines a @code{struct exception}. Version 2.02 of DJGPP will
correct @file{math.h}, and a corrected version is included in the
@file{gcc281b.zip} distribution. The corrected @file{math.h} is
installed into the @file{lib/gcc-lib/djgpp/2.81/include} directory, so
either delete or rename the old version in the @file{include} directory,
or copy the corrected version into @file{include}. Another solution is
to compile with the @samp{-posix} or @samp{-ansi} compiler switch, which
cause @file{math.h} to not define @code{struct exception}.
@node Assembly output, movedata.h, C++ exceptions, Compiling
@comment node-name, next, previous, up
@section How to get GCC to generate assembly code
@cindex Assembly code, generating with GCC
@cindex Listing, assembly and source code
@quest{How can I peek at the assembly code generated by GCC?}
@quest{How can I create a file where I can see the C code and its
assembly translation together?}
@ans{} Use the @samp{-S} (note: @emph{capital} S) switch to GCC, and it
will emit the assembly code to a file with a @file{.s} extension. For
example, the following command:
@example
gcc -O2 -S -c foo.c
@end example
@noindent
will leave the generated assembly code on the file @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:
@example
gcc -c -Wa,-a,-ad [other GCC options] foo.c > foo.lst
@end example
@noindent
which will output the combined C/assembly listing to the file
@file{foo.lst}.
@paragraph{}
If you need to both get the assembly code @emph{and} to compile/link the
program, you can either give the @samp{-save-temps} option to GCC (which
will leave all the temporary files including the @file{.s} file in the
current directory), or use the @samp{-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 @samp{=}.
@node movedata.h, Libraries, Assembly output, Compiling
@comment node-name, next, previous, up
@section What's wrong with @file{sys/movedata.h}?
@cindex sys/movedata.h header, compilation errors
@cindex movedata.h header, compilation problems
@quest{Whenever I try to compile a program that includes the
@file{sys/movedata.h} header file, I get ``parse error'' messages from
the compiler. Can't you guys make your system headers right?}
@ans{} This is a bug in the @file{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 @file{sys/types.h} header before
@file{sys/movedata.h} in your programs.
@node Libraries, , movedata.h, Compiling
@comment node-name, next, previous, up
@section How do I create a library of object files?
@cindex Object libraries, how to create/update
@cindex Libraries, object, how to create/update
@cindex -lfoo, linker switch
@quest{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@dots{}}
@ans{} First, you need to compile all your sources into object @file{.o}
files, like this:
@example
gcc -c -Wall -O2 file1.c
gcc -c -Wall -O2 file2.c
gcc -c -Wall -O2 file3.c
...
@end example
@noindent
The only GCC switch in this example that's required is @samp{-c}, the
rest are just recommended for better code generation and diagnostics.
@paragraph{}
Once you have the object files ready, use the @code{ar} (``Archiver'')
utility to create a library, let's say we'll call it @file{libacme.a},
like this:
@example
ar rvs libacme.a file1.o file2.o file3.o ...
@end example
@noindent
The @samp{rvs} flags tell @samp{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.
@paragraph{}
@cindex Libraries, creating with RHIDE
@cindex Object libraries, creating with RHIDE
If you use @sc{rhide}, you can create a library by specifying a file
with a @file{.a} extension as the main target in the project (choose
@samp{Project | Main Target Name} and enter a file name such as
@file{libfoo.a}).
@paragraph{}
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:
@example
gcc -o myprog.exe myprog.c libacme.a
@end example
@noindent
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
@strong{all} the object files, even those which aren't used by the
program.
@paragraph{}
The name of the library which begins with a @file{lib} and ends with a
@file{.a} extension is a convention used for convenience. When the link
command line includes an argument @samp{-lXXYYZZ}, GCC (and all Unix
compilers) will look for a file @file{libXXYYZZ.a} in every directory
they search by default. So, if your library @file{libacme.a} is
installed in the DJGPP @file{lib} subdirectory, the user can instruct
GCC to look into it by appending @samp{-lacme} to the link command line.
Other systems might be configured to look for different names when a
switch such as @samp{-lfoo} is mentioned. For example, Linux might look
in @file{/usr/lib} for a file @file{libfoo.so.4.1}, while Alpha/VMS will
look for @file{SYS$GNU:[LIBRARIES]FOO.LIB;19}. Windows 98, of course,
will look for something monstrously long like
@w{@file{C:@bs{}Windows@bs{}Program Files@bs{}Vendors@bs{}GNU@bs{}gcc@bs{}libraries@bs{}foo.lib}}.
If you don't follow this convention, you will need to type the full name
of the library file.
@paragraph{}
If you need to update a certain object file in a library, use the same
command @kbd{ar rvs library-name object-name} as above, but only with
the name(s) of the object file(s) you need to replace.
@paragraph{}
@code{ar} is documented in the Binutils docs. To read, type this from
the DOS prompt:
@example
info binutils ar
@end example
@node Running, Graphics, Compiling, Top
@comment node-name, next, previous, up
@chapter Running Compiled Programs
@cindex Run-time problems
This chapter discusses various problems which may happen when running
DJGPP programs under different environments, and gives solutions to them.
@menu
* v2.x crash:: Program which was OK in v1.x bombs in v2.0.
* Crash traceback:: How to make sense out of stack dumps.
* File data corrupted:: The DOS @emph{TEXT}/@emph{BINARY} file issue.
* Screen IO:: Beware of the buffering!
* Distributing:: DJGPP programs are @strong{not} self-contained.
* File handles:: How many file handles can your program use.
@end menu
@node v2.x crash, Crash traceback, Running, Running
@comment node-name, next, previous, up
@section My program crashes only in v2.0!
@cindex Program crashes in v2.0, but not in v1.x
@cindex Uninitialized memory crashes v2.0 programs
@cindex v2.0, program crashes
@cindex DEADBEEF, use to spot uninitialized memory
@cindex Null pointer dereference crashes v2.0 programs
@cindex Crashes, v2.0 programs
@cindex Page fault error message from CWSDPMI
@pindex CWSDPMI crashes programs which dereference NULL pointers
@quest{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?}
@quest{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?}
@ans{} 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 @code{malloc} is always zeroed, but v2 doesn't behave
this way, so your program might exhibit erratic behavior or crash with
@code{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.
@paragraph{}
To check whether this is the source of your grief, include the header
@code{crt0.h} in your @code{main} and set @code{_crt0_startup_flags} to
@code{_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
@code{_crt0_startup_flags} to @code{_CRT0_FLAG_FILL_DEADBEEF} @i{(don't
laugh!)}; this will cause the sbrk()'ed memory to be filled with the
value @code{0xdeadbeef} (@code{-559038737} in signed decimal or
@code{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.
@paragraph{}
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.@: @dfn{NULL pointer protection}).
This feature can be disabled by setting the @code{_CRT0_FLAG_NULLOK} bit
in @code{_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.
@xref{Crash dump, how to debug SIGSEGV, How to begin debugging using the
crash dump info}, for more details about these problems.
@paragraph{}
An insufficient stack size can also be a cause of your program's demise,
see @ref{Stack size, setting the stack size, How much stack can I have
in DJGPP programs?}, below.
@node Crash traceback, File data corrupted, v2.x crash, Running
@comment node-name, next, previous, up
@section What is that gibberish printed when my program crashes?
@cindex Traceback, how to read
@cindex Crash traceback, how to read
@cindex Stack dump, how to read
@pindex SYMIFY, a program to read crash traceback
@pindex REDIR, redirecting stack dump to a file
@quest{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?}
@ans{} Those ``funny-looking numbers'' @emph{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
@samp{SYMIFY} program. @samp{SYMIFY} is included in the
@ftp{basic DJGPP development environment distribution,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2/djdev@value{djgpp-version}.zip}, and
should be in your @file{bin/} subdirectory. To @dfn{symify} the
traceback, make sure that your program was compiled with the @samp{-g}
switch, linked @strong{without} the @samp{-s} switch and @strong{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:
@example
symify your-program-name
@end example
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 @ref{Crash dump, how to
analyze crash dumps, How to begin debugging using the crash dump info}.
@paragraph{}
@cindex Inline assembly, inaccurate SYMIFY output
@pindex SYMIFY, inaccurate report for inline assembly
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.
@paragraph{}
You can ask @samp{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:
@example
symify -o problem.dmp yourprog
@end example
You can also save the raw stack trace (without source info) to a disk file
and submit it to @samp{SYMIFY} later, like this:
@example
symify -i core.dmp yourprog
@end example
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 @ref{Redirect,
redirect the stack trace to a file, How to redirect long messages to a
file}, e.g., with the @samp{REDIR} program which comes with DJGPP.
@paragraph{}
But what if you @emph{didn't} compile your program with @samp{-g}, and you
aren't sure how to recreate the problem which crashed it, after you
recompile? Well, you can submit the stack dump @emph{after} you recompile
your program. Just press that PrintScreen key or otherwise save the stack
trace, then submit it to @samp{SYMIFY} from a file as described above,
after you've recompiled the program. Be sure to give gcc all the
compilation switches (sans @samp{-s}) that you gave it when you originally
compiled your program (in addition to @samp{-g}), including the
optimization switches, or else the addresses shown in the stack trace
might be invalid.
@paragraph{}
@cindex Source line from the EIP, using GDB
@cindex Program counter, converting to source lines
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 @samp{NNNNNNNN},
type this at the GDB prompt:
@example
list *0xNNNNNNNN
@end example
@node File data corrupted, Screen IO, Crash traceback, Running
@comment node-name, next, previous, up
@section Reading and writing binary files
@cindex Files, reading and writing
@cindex Binary data I/O
@cindex fstream truncates files open for read/write
@cindex Truncation of files when using fstream
@quest{I'm reading/writing data files, but the data gets corrupted.}
@quest{My program crashes when I read data files, but the same program
on Unix works OK.}
@quest{When I read a file I get only a small portion of it.}
@quest{I'm trying to open an existing binary file for read/write using
the @code{fstream} class, but no mater what I do, the file is always
truncated after I write to it@dots{}}
@ans{} Are your data files binary? The default file type in DOS is
``text'', even when you use the @code{read} and @code{write} library
functions. Text files get their newlines converted to @samp{CR-LF}
pairs on write and vice versa on read; reading in ``text'' mode stops at
the first @samp{^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 @code{b} flag in
@code{fopen}, or @code{O_BINARY} in @code{open}, or use the
@code{setmode} library function.
@paragraph{}
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.
@paragraph{}
You can also use the low-level @code{_read} and @code{_write} library
functions which give you the direct interface to the DOS file I/O; they
always use binary I/O.
@paragraph{}
Problems with read/write access to binary files via @code{fstream} class
in C@t{++} 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:
@example
fstream inFile;
int fd = open ("foobar", O_RDWR | O_BINARY);
inFile.open (fd);
@end example
@node Screen IO, Distributing, File data corrupted, Running
@comment node-name, next, previous, up
@section Buffered screen I/O surprises
@cindex Screen I/O
@cindex Interactive programs, screen I/O
@cindex gotoxy doesn't work with `printf'
@cindex Color text cannot be printed with `printf'
@cindex printf cannot print color text
@quest{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.}
@quest{Help! I cannot make `gotoxy' work! The text I print appears on
the screen in incorrect locations after I use `gotoxy'!}
@quest{Why does the text appear in the default colors even though I call
`textcolor' and `textbackground'?}
@ans{} Do you write to screen using buffered I/O (@code{fprintf},
@code{fputs} and the like) functions, or send your output to the C@t{++}
@code{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.
@paragraph{}
It is usually a bad idea to use buffered I/O in interactive programs; you
should instead use screen-oriented functions like @code{cprintf} and
@code{cputs.} If you must use buffered I/O, you should be sure that
both @code{stdout} and @code{stderr} are line-buffered or unbuffered (you
can change the buffering by calling the @code{setvbuf} library
function); another solution would be to @code{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 @code{sync} would
be needed to actually cause the output be delivered to the screen.
@paragraph{}
The functions that set text attributes only affect the screen-oriented
output (a.k.a.@: @dfn{conio}) functions (@code{cputs}, @code{cprintf} etc.),
the text written by @code{fprintf} and other @dfn{stdio} functions
doesn't change. This is unlike some 16-bit DOS compilers where
@code{stdio} functions can also print colored text.
@node Distributing, File handles, Screen IO, Running
@comment node-name, next, previous, up
@section What do DJGPP programs need to run?
@cindex Distributing DJGPP programs
@cindex DPMI, required to run DJGPP programs
@cindex DJGPP-compiled programs can't find DPMI
@cindex Stand-alone DJGPP programs that don't need DPMI
@pindex CWSDPMI, should be distributed with DJGPP programs
@pindex PMODE/DJ, can be used to produce stand-alone programs
@quest{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?}
@ans{} No, you don't. You can either (a) bring the @file{CWSDPMI.EXE}
free DPMI host to the target machine and put it in the same directory as
your compiled program or somewhere along the @code{PATH}, or (b) install
another DPMI host (such as QDPMI, 386Max, Windows, etc.) on the target
machine.
@paragraph{}
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. @xref{Emulation, floating-point emulation
issues, Floating-point code without 80387}.
@paragraph{}
@samp{PMODE/DJ} can be bound with your program, so that you have a
single self-sufficient executable, but remember that @samp{PMODE/DJ}
doesn't support virtual memory, so such programs will only run on
machines with enough free physical RAM.
@node File handles, , Distributing, Running
@comment node-name, next, previous, up
@section How many file handles can DJGPP use?
@cindex Files, max open simultaneously
@cindex Handles, maximum available number
@quest{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@dots{}}
@quest{I put a @samp{FILES=60} directive in my @file{CONFIG.SYS}, but my
programs cannot use more than 42 when they run on Windows. Why is
that?}
@ans{} 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@footnote{
Those who want @emph{all} the details should consult a good book about
DOS internals, such as @cite{Undocumented DOS, 2nd ed.} by Andrew
Schullman, or Geoff Chappel's @cite{DOS Internals}.}, but I will try to
explain at least those aspects which directly affect a typical DJGPP
user.
@paragraph{}
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.
@paragraph{}
First, if you create new handles by calling the @code{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 @samp{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.
@paragraph{}
@cindex Inheritance, file handles
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 @dfn{inherited} by the child, unless
the parent sets the special @code{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 @code{dup}@footnote{
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.}.
@paragraph{}
@cindex FILES= directive
The @samp{FILES=} directive comes into play when you call @code{open} or
any of its brethren to create handles. Unlike the handles created by
@code{dup}, @code{open} (and the underlying functions 3Dh or 6Ch of
Interrupt 21h) create handles that are @emph{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 @samp{FILES=} directive. This is because the @samp{FILES=}
directive sets the number of entries in the SFT, the @dfn{System File
Table} maintained by DOS, where all the information about every open
file is kept@footnote{
Each handle created by a call to @code{open} uses up one slot in the
SFT, whereas a handle created by @code{dup} just increments the use
count of a slot that was already in use.}. So, if your
@file{CONFIG.SYS} specifies @samp{FILES=60}, you cannot @code{open} more
than 60 files. After that, a call to @code{open} will fail with
@code{ENFILE} (Too many open files in system).
@paragraph{}
In practice, you won't even be able to get 60 handles if you have
@samp{FILES=60} in your @file{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 @samp{FILES=60}, DOS will only let
you open up to 55 independent handles.
@paragraph{}
@cindex PerVMFiles= directive
@cindex File handles, under Windows
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 @samp{PerVMFiles=} entry in the @samp{[386Enh]}
section of the @file{SYSTEM.INI} file can override that. So on Windows,
you need to consider the @samp{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).
@paragraph{}
@pindex SHARE, limits available file handles
If your system loads @file{SHARE.EXE} during bootstrap, things become
even more complicated. @file{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
@samp{FILES=} directive says, and sometimes even less than that. That
is how somebody who has @samp{FILES=60} on their @file{CONFIG.SYS} could
only get 42 handles on Windows. If you are looking for reasons not to
load @file{SHARE.EXE}, here you have another one.
@node Graphics, Floating point, Running, Top
@comment node-name, next, previous, up
@chapter Writing and Running Graphics Programs
@cindex Graphics issues
This chapter discusses some problems and explains some subtle points
related to graphics programming under DJGPP.
@paragraph{}
Another important source of related information is a tutorial on
@www{graphics programming with DJGPP,
remus.rutgers.edu/~avly/djgpp.html}.
@menu
* Which driver:: What driver to use with your SVGA?
* Direct access:: Under protected-mode it is (almost) forbidden.
* Graphics and Windows:: Windows can get into the way of your programs.
@end menu
@node Which driver, Direct access, Graphics, Graphics
@comment node-name, next, previous, up
@section What GRX driver to use with your SVGA
@cindex Graphics driver setup
@cindex SVGA types supported by GRX
@cindex VESA support by GRX
@pindex GRX, supported SVGA types
@pindex UNIVBE, software VESA 2.0 emulation
@quest{Why won't GRX work with my SVGA adapter in any resolution but the
standard VGA?}
@quest{How do I tell GRX which driver to use with my SVGA?}
@ans{} In order for GRX to work with your SVGA, you should set the
@code{GRX20DRV} environment variable, like this:
@example
set GRX20DRV=et4000 gw 1024 gh 768 nc 256
@end example
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:
@table @samp
@titem ati28800
The ATI 28800 chip-set.
@titem cl5426
Cirrus Logic CL-GD5426 or higher (like CL-GD5428) chip-set.
@titem et4000
Tseng Labs ET4000 chip-set.
@titem mach64
The ATI Mach-64 SVGA.
@titem stdega
The standard EGA adapter.
@titem stdvga
The standard VGA adapter.
@titem VESA
For any VESA-compatible adapter.
@end table
After you set the @code{GRX20DRV} variable, run @file{modetest.exe} to see
what modes you have available.
@paragraph{}
If your chip-set is not one of the above, try the @samp{VESA} driver
because many adapters support the VESA BIOS extensions. If yours
doesn't, try installing a VESA BIOS emulator, like @ftp{UNIVBE,
@SimTel{}/pub/simtelnet/msdos/graphics/univbe51.zip}. The latest
version of UNIVBE and related software is always available @www{from
SciTech Web site, www.scitechsoft.com/}.
@node Direct access, Graphics and Windows, Which driver, Graphics
@comment node-name, next, previous, up
@section Accessing the video memory
@cindex Accessing video memory
@cindex Video memory, direct access
@cindex Graphics, direct video access
@cindex Text-mode video memory access
@cindex Far pointer memory access
@cindex Accessing VBE 2.0 linear frame buffer
@cindex Linear frame buffer access
@cindex VBE 2.0 linear frame buffer access
@quest{I try to access the video memory at @code{0xa0000}, but my
program crashes with SIGSEGV@dots{}}
@quest{How can I access the text-mode video memory of my VGA?}
@ans{} 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 @code{_farpeekb} and
@code{_farpokew}; they are described in the C Library reference.
@xref{Xfer, more details on using ``farptr'' functions to access
absolute addresses in low memory, How to move data between your program
and conventional memory}, below.
@paragraph{}
For text-mode screen updates, you can use the @code{ScreenUpdate} and
@code{ScreenUpdateLine} library functions to quickly update the screen
from a text buffer.
@paragraph{}
Using the @code{_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 @ref{Fat DS, using the
``nearptr'' access facilities, Fast access to absolute addresses}, as
described below.
@paragraph{}
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 @ftp{VBE example code by Charles Sandmann,
ftp.neosoft.com/pub/users/s/sandmann/vbe.zip}. You can also reach this
file @www{via the Web, www.rt66.com/~brennan/djgpp/vbe.zip}.
Some examples of how to access video memory from DJGPP programs are
available @www{from Brennan Underwood's Web page,
brennan.home.ml.org/djgpp/}.
@node Graphics and Windows, , Direct access, Graphics
@comment node-name, next, previous, up
@section Graphics screen restoring under Windows
@cindex Screen contents not restored under Windows
@cindex Graphics screen messed up under Windows
@cindex Graphics programs, and Windows DOS Mode
@cindex DOS Mode, Windows suggests for graphics programs
@pindex Windows messes up graphics screen
@pindex Windows, wants to run graphics programs in DOS Mode
@quest{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?}
@quest{I cannot run my program which uses Allegro: Windows 9X says the
program would work better in DOS Mode@dots{}}
@ans{} 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 @emph{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.
@paragraph{}
The only reasonable thing to do is to dedicate a ``hotkey'' in your
application (e.g., @kbd{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 @code{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.
@paragraph{}
Windows 9X @emph{does} save and restore the SVGA state, but only if you
task-switch with the @kbd{Alt-@key{TAB}} key. If the switch happens
because of anything else, like a window popping up, or you pressing the
@samp{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:
@display
@cartouche
This application cannot be restored and will be terminated.
@end cartouche
@end display
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:
@itemize @bullet{}
@item
Right-click on the program's @file{.exe} file in the @samp{Explorer} or
in @samp{My Computer}, then click on @samp{Properties}.
@item
Click on the @samp{Program} tab, then press the @samp{Advanced} button,
and change the advanced properties as follows:
@itemize @minus{}
@item
uncheck the @samp{Suggest DOS Mode as necessary} option;
@item
check the @samp{DOS Mode} option;
@item
uncheck the @samp{Warn before entering DOS Mode} option;
@item
check the @samp{Prevent MS DOS programs from detecting Windows} option;
@item
uncheck the @samp{DOS Mode} option.
@end itemize
@item
Finally, click the @samp{OK} button twice.
@end itemize
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.
@node Floating point, Debugging, Graphics, Top
@comment node-name, next, previous, up
@chapter Floating Point Issues and FP Emulation
@cindex Floating-point emulation
@cindex Floating-point issues
@cindex Emulation, floating-point
This chapter deals with issues pertaining to floating-point code and
floating-point emulation under DJGPP.
@menu
* Emulation:: What are your emulation options.
* Other emulators:: You can't use them.
* OS2 emulation:: It doesn't serve DJGPP programs.
* -msoft-float:: This GCC switch isn't supported.
* Numeric exceptions:: Don't give us these NaN's!
* Emulator accuracy:: Not always as good as we'd like.
* SIGFPE with ObjC:: Objective C cannot run without FPU.
* SIGFPE in ldexp:: Some libm functions bomb.
@end menu
@node Emulation, Other emulators, Floating point, Floating point
@comment node-name, next, previous, up
@section Floating-point code without 80387
@cindex Emulator library
@cindex Library, floating-point emulation
@cindex Distributing DJGPP programs, FP emulator
@cindex Floating-point emulation doesn't work
@pindex libemu.a FP emulation library
@pindex emu387.dxe, distribution with DJGPP programs
@pindex WMEMU, an alternative floating-point emulator
@pindex WMEMU causes undefined references when linking
@quest{I don't have an 80387. How do I compile and run floating point
programs?}
@quest{What shall I install on a target machine which lacks hardware
floating-point support?}
@ans{} Programs which use floating point computations and could be run
on machines without an 80387 should either be linked with the
@file{libemu.a} emulation library (add @samp{-lemu} to your link command
line) or be allowed to dynamically load the @file{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 @file{.exe} file
(the emulator functions will be used only if no hardware floating point
support is detected at runtime). You should @strong{always} do one of
the above when you distribute floating-point programs.
@paragraph{}
A few users reported that the emulation won't work for them unless they
explicitly tell DJGPP there is no x87 hardware, like this:
@example
set 387=N
set emu387=c:/djgpp/bin/emu387.dxe
@end example
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
@CWS{} and ask him for guidance.
@paragraph{}
There is an alternative FP emulator called @samp{WMEMU} (get the file
@file{v2misc/wmemu@value{wmemu-version}b.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 @file{wmemu387.dxe}, or
distribute the source or objects to your entire program, if you link it
with @file{libwmemu.a}). Its advantage is that with @samp{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
@file{libwmemu.a} without recompiling it.) Note, however, that even
@samp{WMEMU} doesn't solve all the problems of debugging FP programs on
a non-FPU machine (e.g., emulating flags doesn't work).
@node Other emulators, OS2 emulation, Emulation, Floating point
@comment node-name, next, previous, up
@section Other FP emulators cannot be used with DJGPP
@cindex Floating-point emulation, non-DJGPP emulators
@cindex Non-DJGPP floating-point emulators
@pindex Q87, an emulator compatible with DJGPP
@quest{I have an 80387 emulator installed in my @file{AUTOEXEC.BAT}, but
DJGPP-compiled floating point programs still doesn't work. Why?}
@ans{} DJGPP switches the CPU to @emph{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 @emph{must} use
emulators which are designed for DJGPP. Apart of @samp{emu387} and
@samp{WMEMU}, the only other emulator known to work with DJGPP is
@samp{Q87} from QuickWare. @samp{Q87} is shareware and is available
@www{from the QuickWare Web site, www.weblane.com/quickware}.
@node OS2 emulation, -msoft-float, Other emulators, Floating point
@comment node-name, next, previous, up
@section Floating-point emulation under OS/2
@cindex Floating-point emulation, under OS/2
@pindex OS/2, floating point emulation
@quest{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?}
@ans{} OS/2 installs an emulator for native OS/2 images, but does not
provide FPU emulation for DOS sessions.
@node -msoft-float, Numeric exceptions, OS2 emulation, Floating point
@comment node-name, next, previous, up
@section DJGPP doesn't support @samp{-msoft-float}
@cindex -msoft-float switch to GCC
@cindex Floating-point emulation, -msoft-float switch
@pindex GCC, -msoft-float switch
@quest{I've read in the GCC Info file that gcc has a @samp{-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?}
@ans{} The GCC Info file also says that the library required by
@samp{-msoft-float} is @strong{not} part of the GNU C compiler. As nobody
wrote such a library for DJGPP (yet), this option currently isn't
supported.
@node Numeric exceptions, Emulator accuracy, -msoft-float, Floating point
@comment node-name, next, previous, up
@section Numeric exceptions---sometimes
@cindex Numeric exception, program crash
@cindex Crash, numeric exception
@cindex Programs crash, numeric exception
@cindex Coprocessor setup, change with _control87
@cindex _control87, change coprocessor setup
@quest{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?}
@ans{} 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 @dfn{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 @code{_control87} can be
used from within a program to set the coprocessor to a non-default
state.
@node Emulator accuracy, SIGFPE with ObjC, Numeric exceptions, Floating point
@comment node-name, next, previous, up
@section Floating point inaccuracies when using emulator
@cindex Inaccuracies, using emulator
@cindex Emulator, floating-point inaccuracies
@cindex Pi, accurate computation
@cindex atan, inaccuracies with FP emulator
@quest{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
@strong{not} using a buggy Pentium CPU.)}
@ans{} 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 @code{atan} function. So if you use
@code{atan(1.)} to get the value of @samp{Pi}, that might be your problem.
Solution: make @samp{Pi} a constant, as God intended. The header file
@ifset html
@code{<math.h>}
@end ifset
@ifclear html
@code{}
@end ifclear
includes the constant @code{M_PI} which you can use; or get the value of
@www{@b{Pi} from the net, www.diku.dk/~terra/pi.html}.
@node SIGFPE with ObjC, SIGFPE in ldexp, Emulator accuracy, Floating point
@comment node-name, next, previous, up
@section Floating point exception in Objective-C programs
@cindex Objective-C programs crash with FP exception
@cindex Floating-point exception in Objective-C program
@pindex Objective-C, cannot run on machines without FPU
@quest{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@dots{}}
@ans{} 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 @www{via the Web,
www.delorie.com/djgpp/mail-archives/djgpp/1996/05/05/11:05:21}.
You will have to get the GCC source distribution @file{gcc2721s.zip},
install the above patch, rebuild @file{cc1obj.exe}, and then recompile
@file{libobjc.a} to make the problem go away.
@node SIGFPE in ldexp, , SIGFPE with ObjC, Floating point
@comment node-name, next, previous, up
@section Floating point exception in libm functions
@cindex ldexp crashes programs with FP exception
@cindex Functions from libm.a crash with SIGFPE
@cindex Math functions crash with SIGFPE
@quest{When I use the @code{ldexp} function, my program crashes with
SIGFPE. What's wrong?}
@ans{} There is a bug in the scaling code in @file{libm.a} library
released with DJGPP v2.0 which affects several library functions such as
@code{ldexp}. A work-around is to link without @samp{-lm} switch; this
will cause @samp{GCC} to use math functions from @file{libc.a}. If you
need math functions which are only in @file{libm.a}, or if you need
@file{libm.a} for better numerical performance, @ftp{a patched version
of libm is available, ftp.lstm.ruhr-uni-bochum.de/pub/djgpp/libm.zip},
courtesy of @mail{Tom Demmer, Demmer@@LStM.Ruhr-Uni-Bochum.De}. DJGPP
v2.01 corrects this bug, so upgrade to that version if you can.
@node Debugging, Profiling, Floating point, Top
@comment node-name, next, previous, up
@chapter Debugging DJGPP Programs
@cindex Debugging issues
This chapter discusses the debuggers you can use with DJGPP and answers
some of the questions you might have when debugging DJGPP programs.
@menu
* How to debug:: What should you do to debug a program.
* Crash dump:: How to use the crash dump info.
* Old QDPMI:: Some QDPMI versions will crash the debugger.
* GDB needs COFF:: GDB can't use the @b{.exe} program.
* Debug graphics:: Debugging GUI programs.
* GDB and C++ source:: Problems with non-@b{.cc} extensions.
* C++ classes in GDB:: Class members' names in GDB.
* Included source:: Debuggers have problems with included files.
* Static vars:: GDB might not let you debug them.
* Debugging woes:: Some programs which cannot be debugged.
@end menu
@node How to debug, Crash dump, Debugging, Debugging
@comment node-name, next, previous, up
@section How to run a DJGPP program under debugger
@cindex Debugger, usage
@cindex Debuggers for DJGPP programs
@cindex Compilation for debugging
@cindex Floating-point, debugger support
@cindex DXE can be debugged with EDEBUG32
@pindex GDB, debugging DJGPP programs
@pindex FSDB, the full-screen debugger
@pindex GCC, compiling for debugging
@pindex GDB, how is it different on MS-DOS
@pindex GDB, init file name
@pindex GDB, name of the READLINE init file
@pindex GDB doesn't pass command-line arguments to debuggee
@pindex GDB, slow loading of symbols and sources
@pindex GDB, conflicts with file redirection
@pindex EDEBUG32 can debug a DXE
@pindex RHIDE, includes an integrated debugger
@quest{How do I debug my programs?}
@ans{} First, remember to use the @samp{-g} switch when you compile and
link. This puts debugging information into your executable. When
linking, don't use the @samp{-s} switch. Here are a few examples of
compilation and link command lines when you intend to debug a program:
@example
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
@end example
Note that with @samp{gcc}, you can use optimization switches when
compiling with @samp{-g.} To use stabs debugging, compile with
@samp{-gstabs3} or @samp{-gstabs+} instead of @samp{-g}.
@paragraph{}
Then, to debug the program, use a command line like this (here for
@samp{gdb}):
@example
gdb myprog.exe
@end example
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:
@example
gdb myprog
@end example
You can use one of several available debuggers with DJGPP:
@enumerate a
@item
@sc{rhide}, the DJGPP IDE by Robert Hoehne is available @ftp{from the
DJGPP archives,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2apps/rhide@value{rhide-version}b.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.
@item
@samp{RHGDB}, a stand-alone version of GDB with a Turbo Vision user
interface. @samp{RHGDB} is part of the @sc{rhide} distribution; it only
supports part of GDB features.
@item
@samp{FSDB}, the full-screen debugger, from the @samp{djdev}
distribution. This presents a user interface like that of Borland's
Turbo Debugger, but unlike TD, @strong{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 @samp{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 @samp{FSDB} is that you cannot
easily examine the contents of complex data structures. Remember to
prepend an underscore @kbd{_} to the names of C identifiers when you use
them with @samp{FSDB}; for C@t{++} programs you will have to find out the
mangled names of static class variables and methods to make @samp{FSDB}
understand them.
@item
@ftp{@samp{GDB},
@SimTel{}/pub/simtelnet/gnu/djgpp/v2gnu/gdb@value{gdb-version}b.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
@samp{GDB} on Unix should know about the following important differences
in its operation on MS-DOS:
@itemize @bullet{}
@item
The command-line arguments can be only passed to the debuggee@footnote{
That's the program being debugged, in case you didn't know.}
from within the debugger (use the @samp{set args} or @samp{run}
commands), not from the @samp{GDB} command line.
@item
@samp{GDB} is currently configured for DJGPP in a way that makes loading
a program and reading a source file when a breakpoint is hit
@strong{exceedingly} slow: it can take more than a minute for a very
large program. Be patient and don't decide that @samp{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.
@item
@samp{GDB} doesn't know about PC-specific keys, so you cannot use the
arrow keys for command history editing. Use ASCII control keys instead
(@kbd{^F} for forward character, @kbd{^B} for backward character,
@kbd{^P} for previous line, @kbd{^N} for next line, etc.).
@item
The debugger and the debuggee share their file handles. This means, for
example, that if your program redirects or closes its @code{stdin} or
@code{stdout}, you will be unable to communicate with @samp{GDB}.
@item
The initial commands are read from a file named @file{gdb.ini} instead
of @file{.gdbinit}, because MS-DOS doesn't allow file names with leading
dots.
@item
@samp{GDB} uses the GNU @samp{readline} package for its input. The
@samp{readline} init file (@file{~/.inputrc} on Unix) is called
@file{/inputrc} on MS-DOS and should be in the root directory of the
current drive.
@end itemize
@item
@samp{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
(@pxref{DXE, explanation of what a DXE is, What is DXE?}), because
@samp{GDB} doesn't support debugging DXEs.
@end enumerate
You invoke any debugger like this:
@ifset html
@example
<debugger-name> <program> <args...>
@end example
@end ifset
@ifclear html
@example
@end example
@end ifclear
@node Crash dump, Old QDPMI, How to debug, Debugging
@comment node-name, next, previous, up
@section How to begin debugging using the crash dump info
@cindex Crash message, how to interpret
@cindex Debugging programs which crash
@quest{My program crashed with SIGSEGV, but I'm unsure how to begin
debugging it@dots{}}
@quest{Can you help me figure out all those funny numbers printed when
my program crashes?}
@cindex Crash traceback, saving to a file
@ans{} 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 @key{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:
@example
redir -e crash.txt myprog [arguments to the program go here]
@end example
@noindent
(here I used the @code{redir} program supplied with DJGPP; the @samp{-e}
switch tells it to redirect the standard error stream to the named
file).
@paragraph{}
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 @sc{rhide}. Without this step, you might erroneously try to debug
the wrong program.
@paragraph{}
The next step in the debugging is to find out where in the code did the
program crash. The @code{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 @code{__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. @xref{Crash traceback, how to
use @code{SYMIFY}, The crash traceback}, for more details about the call
frame traceback and @code{SYMIFY} usage.
@paragraph{}
If you compiled your program without the @samp{-g} switch, or if you
stripped the debugging symbols (e.g., using the @samp{-s} linker
switch), you will have to rebuild the program with @samp{-g} and without
@samp{-s}, before you continue.
@paragraph{}
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:
@example
Exiting due to signal SIGSEGV
Page Fault at eip=00008e89, error=0004
@end example
@noindent
(the actual text in your case will be different). The following table
lists common causes for each type of crash:
@table @samp
@titem Page Fault
@cindex Page Fault message
@cindex NULL pointer
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 @code{malloc}
(did your code check for that?). An uninitialized pointer holds some
random garbage value; it can come from a missing call to @code{malloc}.
@paragraph{}
If the message says @samp{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. @xref{HW Int pitfalls, installing
hardware interrupt handlers, Hardware interrupt hooking has its
subtleties}, for more about this.
@paragraph{}
@titem General Protection Fault
@cindex General Protection Fault message
This can be caused by a variety of reasons:
@itemize @minus{}
@item
use of an uninitialized or a garbled pointer (beyond the limit of the DS
segment printed at the time of crash);
@item
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 @code{int} to a function that
expects a @code{double}, or passing buffers to a library function
without sufficient space to hold the results;
@item
stack overflow.
@end itemize
@paragraph{}
Overrunning the stack frame usually manifests itself by abnormal values
of the @sc{ebp} or @sc{esp} registers, printed right below the first two
lines. The normal case is when @sc{esp} is @emph{slightly smaller} than
@sc{ebp}, smaller than the limit of the @sc{ss} segment, and usually
@emph{larger} than @sc{eip}@footnote{
Programs that create machine code in @code{malloc}ed storage and then
jump into it could have their @sc{eip} above @sc{ebp}. The Allegro
library utilizes this technique in some of its functions.}; anything
else is a clear sign of a disaster.
@paragraph{}
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.
@paragraph{}
Suspect a stack overflow if the @sc{ebp} and @sc{esp} values are close
to one another, but both very low (the stack grows @emph{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. @xref{Stack size, changing stack size, How much
stack can I have in DJGPP programs?}, 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 @code{malloc}.
@paragraph{}
@titem Stack Fault
@cindex Stack Fault message
Usually means a stack overflow, but can also happen if your code
overruns the stack frame (see above).
@paragraph{}
@titemx Floating Point exception
@titemx Coprocessor overrun
@titemx Overflow
@titeml Division by Zero
@cindex Floating Point exception message
These (and some additional) messages, printed when the program crashes
due to signal @code{SIGFPE}, mean some error in floating-point
computations, like division by zero or overflow. Sometimes such errors
happen when an @code{int} is passed to a function that expects a
@code{float} or a @code{double}.
@paragraph{}
@titem Cannot continue from exception, exiting due to signal 0123
@cindex Cannot continue from exception message
This message is printed if your program installed a handler for a fatal
signal such as @code{SIGSEGV} (0123 in hex is the numeric code of
@code{SIGSEGV}; see the header @file{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.
@paragraph{}
If you indeed wanted @code{SIGSEGV} to be generated in that case, the
way to solve such problems is to modify your signal handler so that it
calls either @code{exit} or @code{longjmp}. If @code{SIGSEGV} should
not have been triggered, debug this as described below.
@paragraph{}
@titem Invalid TSS in RMCB
@cindex Invalid TSS in RMCB message
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
@code{abort}: v2.0 had a bug in its library whereby calling @code{abort}
would bypass the cleanup code that restored the keyboard interrupt
hooked by the DJGPP startup code; v2.01 solves this bug.
@paragraph{}
Using the @code{itimer} facility can also cause such crashes if the
program exits abnormally, or doesn't disable the timer before it exits.
@paragraph{}
@titem Double Fault
@cindex Double Fault message, after Ctrl-C, Ctrl-BREAK
If this message appears when you run your program under CWSDPR0 and
press the Interrupt key (@kbd{Ctrl-@key{C}} or @kbd{Ctrl-@key{BREAK}}),
then this is expected behavior (the @code{SIGINT} generation works by
invalidating the @sc{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 @code{Page Fault}.
@paragraph{}
@titem Control-Break Pressed
@titeml Control-C Pressed
These are not real crashes, but are listed here for completeness. They
are printed when @kbd{Ctrl-@key{BREAK}} or @kbd{Ctrl-@key{C}} is
pressed, and by default abort the program due to signal @code{SIGINT}.
@end table
@paragraph{}
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
@sc{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.
@paragraph{}
People which are less lucky have their programs crash inside library
functions for which @code{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:
@itemize @bullet{}
@item
Begin with the last call frame that @code{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.
@item
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
(@pxref{Patched libc, libc with debug info, Where to find the best
library for DJGPP}), or (b) get the sources of the library, and
recompile it with the @samp{-g} compiler switch. After re-linking the
program, cause it to crash and run @code{SYMIFY} to get a full
description of the place where it dies.
@item
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 @samp{-g} switch. Then run
your program again, and when it crashes, @code{SYMIFY} should be able to
find the line number info for the entire traceback.
@item
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:
@itemize @minus{}
@item
Load the program into a debugger.
@item
Display the instruction at @sc{eip} whose value is printed on the second
line of the crash message. For example, with GDB, use the @kbd{x/i
eip-value} command.
@item
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.
@item
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:
@enumerate a
@item
A pointer whose value is below 4096 (1000 hex), or above the limit of
the @sc{ds} segment.
@item
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.
@item
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).
@end enumerate
@item
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.
@end itemize
@end itemize
@node Old QDPMI, GDB needs COFF, Crash dump, Debugging
@comment node-name, next, previous, up
@section You need QEMM 7.53 or later
@cindex Debugger crashes under QEMM/QDPMI
@cindex Disabling QDPMI
@pindex QEMM crashes debugger
@pindex QDPMI crashes debugger
@pindex QDPMI, how to disable
@pindex GDB crashes under QEMM/QDPMI
@pindex FSDB crashes under QEMM/QDPMI
@quest{Whenever I call any DJGPP debugger to debug my program, it crashes
immediately.}
@ans{} 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 @samp{CWSDPMI} as your DPMI host. To disable QEMM DPMI services
either uninstall QDPMI, or go to the QEMM directory and issue the
following command:
@example
qdpmi off
@end example
@node GDB needs COFF, Debug graphics, Old QDPMI, Debugging
@comment node-name, next, previous, up
@section GDB would not debug unless it sees COFF output
@cindex Debugging with GDB, needs COFF output
@cindex COFF output from linker, how to get
@pindex GDB needs COFF output
@pindex Linker, how to get COFF output
@quest{I try invoking GDB on my program, but it says: ``not in executable
format: File format not recognized.'' Huh?}
@ans{} Most probably, you've invoked GDB from DJGPP v2.0 on a
@file{.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
@file{.exe} and a COFF file, you should make your link command line look
this way:
@example
gcc -o foo foo.o
@end example
instead of
@example
gcc -o foo.exe foo.o
@end example
(the latter will only produce @file{foo.exe}, while the former produces
both @file{foo}, the COFF executable which gdb needs, and
@file{foo.exe}).
@paragraph{}
To produce a COFF file from a @file{.exe} program, use the
@file{EXE2COFF} program which comes with DJGPP, like this:
@example
exe2coff foo.exe
@end example
Debuggers which come with DJGPP v2.01 can debug COFF and .exe programs
alike, so upgrading to v2.01 should solve this problem.
@node Debug graphics, GDB and C++ source, GDB needs COFF, Debugging
@comment node-name, next, previous, up
@section How to debug a graphics program
@cindex Debugging graphics programs
@cindex Graphics programs, debugging
@cindex Monochrome monitor, redirecting screen output
@cindex Code page change might prevent MSHELL from working
@cindex Monochrome monitor device driver
@cindex Monochrome monitor, support in RHIDE
@pindex GDB, debugging graphics programs
@pindex MSHELL, redirecting screen output
@pindex MSHELL fails because of TSR programs
@pindex CHCP DOS command might prevent MSHELL from working
@pindex MDA device driver for redirecting debug output
@pindex EMM386, conflicts with dual-monitor systems
@pindex RHIDE, and monochrome display
@quest{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.}
@ans{} Redirect the debugger output to your printer, like this:
@ifset html
@example
gdb myprog > prn
@end example
@end ifset
@ifclear html
@example
gdb myprog > prn
@end example
@end ifclear
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.
@paragraph{}
Beginning with version 1.1, @sc{rhide} and @samp{RHGDB} support
debugging graphics programs, so upgrade to latest version of @sc{rhide}
and use its built-in debugger or the stand-alone @samp{RHGDB} subset.
This support doesn't work for all video modes, but the standard VGA
modes and VESA modes are supported.
@paragraph{}
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 @kbd{Alt-@key{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 @ftp{FSDB with graphics support,
ftp.delorie.com/pub/djgpp/contrib/gnudebug.zip} is available that knows
about many graphics modes. The same distribution can also be found
@ftp{on the Oulu repository,
x2ftp.oulu.fi/pub/msdos/programming/djgpp2/gnudebug.zip}.
@paragraph{}
As yet another possibility, consider using the @samp{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. @samp{MSHELL} was written by @DJ
and is available @ftp{from DJ's server,
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 @samp{MSHELL} won't help you. For example,
changing the code page (with the DOS @samp{CHCP} or @samp{MODE}
commands) might do this.
@paragraph{}
@sc{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.
@paragraph{}
If you have any problems with dual-monitor support, in particular with
@sc{rhide}, make sure your memory manager doesn't grab the @code{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.
@paragraph{}
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
@www{BinaryInfosys' home page,
www.binaryinfosys.com/bis/files/mda.exe}.
@node GDB and C++ source, C++ classes in GDB, Debug graphics, Debugging
@comment node-name, next, previous, up
@section GDB finds only @file{.cc} source
@cindex Debugging C@t{++} programs
@cindex Debugger cannot find C@t{++} source
@cindex C@t{++} source, debugger cannot find
@pindex GCC, assumes C@t{++} source is @file{.cc}
@quest{When I try to debug my C@t{++} programs, the debugger claims it can't
find the source file:}
@example
file.cc: No such file or directory.
@end example
@emph{The source file @strong{is} there, but it's called
@file{file.cpp}, not @file{file.cc.} Why does this happen?}
@ans{} It's a bug in GCC 2.7.2 and earlier. It erroneously assumes
that a C@t{++} source always has a @file{.cc} extension. If you are using
GCC 2.7.2.1 or earlier, you'd better call your C@t{++} files @file{*.cc}.
If this is unacceptable, you can work around this bug by invoking
@samp{cc1plus} and the assembler pass manually. The bug in GCC
manifests itself in that @samp{cc1plus} is called with the option
@samp{@w{-dumpbase file.cc}.} If you replace this with
@samp{@w{-dumpbase file.cpp}} (or whatever your extension is), the
debugger will happily find your sources.
@paragraph{}
GCC 2.8.0 and later corrects this bug, so upgrading is also a solution.
@node C++ classes in GDB, Included source, GDB and C++ source, Debugging
@comment node-name, next, previous, up
@section Can GDB print class members?
@cindex Class method name in GDB
@cindex Class static variable name in GDB
@cindex Method name in C@t{++}, how to pass to GDB
@cindex C@t{++} class variables under GDB
@cindex C@t{++} method names under GDB
@cindex Source language is not recognized by GDB in C@t{++} programs
@cindex Mangling C@t{++} identifiers, GNU style
@cindex C@t{++} debugging with stabs information
@pindex GDB, how to use C@t{++} method names
@pindex GDB, how to use C@t{++} class variables' names
@pindex GDB doesn't recognize source language
@quest{It seems that GDB doesn't recognize C@t{++} 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?}
@ans{} No, you don't. @samp{GDB} @emph{does} allow you to use the
original names, it's just that it usually treats the @kbd{::} in their
names as word delimiters. Include the name of the method or a class
static variable in single quotes, and @samp{GDB} will recognize them as
a single word. For example, if your class @code{CMPForward} has a
method named @code{go} which you need to put a breakpoint in, use the
following command:
@example
b 'CMPForward::go'
@end example
Other @samp{GDB} features that might be useful in this context are the
various demangling options, like @samp{set print demangle}, @samp{set
demangle-style} etc.; look them up in the GDB on-line docs.
@paragraph{}
@pindex gsymify, a substitute for SYMIFY for stabs debugging
However, there are some cases where you won't be able to get GDB to
demangle C@t{++} 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@t{++}-specific support. If you need a description
of the GNU style of mangling C@t{++} names (so you could demangle them
yourself), look in the GDB or Libg++ source distribution, in the
libiberty directory, for a file named @file{cplus-demangle.c}. If you
really need full C@t{++} 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: @samp{FSDB},
@samp{EDEBUG32} and @samp{SYMIFY} don't understand stabs, so you will
have to compile with @samp{-gcoff} option to use these utilities
(@sc{rhide} distribution includes a utility called @samp{gsymify} that
can be used instead of @samp{SYMIFY} with stabs debugging info).
@paragraph{}
Note that, as the debugger built into @sc{rhide} uses GDB code, it will
also sometimes have such problems with debugging C@t{++} programs.
@node Included source, Static vars, C++ classes in GDB, Debugging
@comment node-name, next, previous, up
@section GDB cannot list source that was #include'd
@cindex Debugger doesn't know about #include'd source
@cindex Including source code, problems with debugging
@cindex Debugging C/C@t{++} code generated by another program
@pindex Flex, debugging generated code
@pindex Bison, debugging generated code
@pindex Yacc, debugging generated code
@pindex Lex, debugging generated code
@pindex F2C, debugging generated code
@quest{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@dots{}}
@quest{I cannot debug code produced by Flex, or Bison, or F2C, because
GDB somehow messes up all the source file and line number info!}
@quest{Why can't I step with a debugger into an inline function defined
in a header file?}
@ans{} 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 @samp{F2C} or @samp{Bison}, @mail{Duncan Murdoch,
D.J.Murdoch@@bristol.ac.uk} suggests a work-around: to copy the original
source file (@file{.y}, @file{.f}, etc.) over the generated C file. For
example, here's how you should go about debugging a Fortran program
@file{myprog.f} using @samp{GCC}, @samp{F2C} and @samp{GDB}:
@enumerate
@item
Run @samp{f2c} with the @samp{-g} option:
@example
f2c -g myprog.f
@end example
@item
Compile using @samp{gcc} with the @samp{-g} option:
@example
gcc -g myprog.c -o myprog.exe -lf2c -lm
@end example
@item
Copy the original Fortran source over the generated C:
@example
copy myprog.f myprog.c
@end example
@item
Debug with @samp{gdb}:
@example
gdb myprog.exe
@end example
@end enumerate
@node Static vars, Debugging woes, Included source, Debugging
@comment node-name, next, previous, up
@section GDB cannot display or set static uninitialized variables
@cindex Static uninitialized variables, failure debugging
@cindex Display or set static variables inside debugger
@pindex GDB fails to set or display static variables
@pindex RHGDB fails to set or display static variables
@pindex RHIDE fails to set or display static variables
@quest{Why can't I set or display the values of some static variables in
my program?}
@ans{} 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 @code{.bss} section of the
program). A work-around is to initialize these variables, which causes
the linker to put them into the @code{.data} section. Another solution
is to use the stabs debugging support; latest versions of GCC include
this support, so upgrade.
@node Debugging woes, , Static vars, Debugging
@comment node-name, next, previous, up
@section Debuggers choke on some programs @dots{}
@cindex Signals in debugged programs
@cindex Debugger crashes on programs which use exceptions
@cindex Floating-point emulation under debugger
@cindex Ctrl-C in debugged programs
@cindex Debugger crashes on programs compiled for profiling
@cindex Profiled programs crash under debugger
@cindex Keyboard interrupt cannot be hooked under debugger
@cindex Debugger doesn't pass signals to debuggee
@cindex Debugger GP Faults on Windows 3.X
@cindex Single-stepping doesn't work in GDB on Windows 3.X
@cindex Single-stepping doesn't work in RHIDE on Windows 3.X
@cindex Breakpoints don't work in GDB under Windows
@cindex Watchpoints don't work in GDB under Windows
@pindex WMEMU, use when debugging FP programs on non-FPU machine
@pindex GDB GP Faults on breakpoint/watchpoint under Windows
@pindex RHIDE debugger GP Faults on breakpoints under Windows
@quest{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)!}
@quest{I cannot debug any program which catches signals!!??}
@quest{I compiled my program with @samp{-pg} switch, and now I cannot
debug it@dots{}}
@quest{When my program hits a breakpoint in GDB, the debugger reports
SIGSEGV, but only under Windows@dots{}}
@ans{} 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
@code{symify} can identify; programs using @code{alarm} or
@code{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
@samp{WMEMU} as your emulator, but even @samp{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.
@paragraph{}
At least some of these limitations will be fixed in future versions of
DJGPP. In case you need a @kbd{Ctrl-@key{C}} key-press to go to the
debuggee instead of the debugger, a work-around is available: use the
@kbd{Alt-Numeric-3} (that is, press the @key{Alt} key, the press and
release the @key{3} key on the numeric keypad.
Some programs (but not Emacs) will also treat the @kbd{Ctrl-@key{2}}
key-press as @kbd{Ctrl-@key{C}}.
@paragraph{}
Beginning with version 1.1, the debugger built into @sc{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 @sc{rhide}.
@paragraph{}
Another known problem is that @samp{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 @emph{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.
@samp{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 @samp{GDB}, you will have to
explicitly use the @samp{hbreak} and @samp{thbreak} (instead of
@samp{break} and @samp{tbreak}) commands which set hardware breakpoints.
This works with DJGPP ports of GDB 4.16 and later. Note that @samp{GDB}
uses the ordinary breakpoints to implement the @samp{step}, @samp{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 @sc{rhide} under Windows 3.X.
@node Profiling, Performance, Debugging, Top
@comment node-name, next, previous, up
@chapter Profiling DJGPP Programs
@cindex Profiling issues
This chapter explains how to optimize your program for speed using the
profiler, and discusses some problems you might have with it.
@menu
* How to profile:: What should you do to profile a program.
* Profiled crash:: Programs compiled with -pg crash.
* Gprof needs COFF:: Gprof doesn't like @b{.exe} executable.
* Gprof docs:: Look on Gprof man page for its docs.
* IO bound programs:: How their profiles look.
* No profile:: Where is the profile?
@end menu
@node How to profile, Profiled crash, Profiling, Profiling
@comment node-name, next, previous, up
@section How to profile a DJGPP program
@cindex Profiling DJGPP programs
@cindex DJGPP programs, profiling
@cindex Optimizing DJGPP programs
@pindex Gprof, the GNU profiler
@quest{How can I profile my program to see where it spends most of its
run time?}
@ans{} DJGPP includes a profiling facility. To use it, compile and link
with @samp{-pg} option, run your program as you usually would, then run a
program called @samp{gprof}:
@example
gprof myprog
@end example
@noindent
(change @samp{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.
@paragraph{}
@samp{Gprof} is further documented in the Binutils docs as part of the
@ftp{GNU Binutils distribution,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2gnu/bnu@value{bnu-version}b.zip}.
@node Profiled crash, Gprof needs COFF, How to profile, Profiling
@comment node-name, next, previous, up
@section Programs compiled with -pg crash when run
@cindex Programs crash when compiled for profiling
@cindex Programs run slowly when compiled with -pg
@cindex Profiling, program crashes or runs slowly
@cindex Monochrome display and profiling
@quest{I cannot profile my program: when I compile it with -pg, it
crashes or wedges my machine!}
@quest{When I compile my program with -pg, it runs much slower. Does
the profiling code have such a huge overhead?}
@quest{I profiled my program, but the profile contains an entry
@code{_mono_putc} which I don't use, and which eats up about 70% of
execution time!}
@quest{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?}
@ans{} DJGPP v2.01 has a bug in one of its library functions which is
linked into your program when it is compiled with the @samp{-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.
@paragraph{}
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
(@pxref{Patched libc, a better library, Where to find the best library
for DJGPP}) 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 @samp{-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.
@node Gprof needs COFF, Gprof docs, Profiled crash, Profiling
@comment node-name, next, previous, up
@section Gprof won't work unless it can find COFF executable
@cindex Profiling DJGPP programs, need COFF output
@cindex COFF output, required for profiling
@cindex Bad format, profiler error message
@pindex Gprof cannot find program
@pindex Gprof says ``bad format''
@quest{When I run @samp{Gprof}, it complains that it cannot find my
program. But I've just run it!!}
@quest{I run @samp{Gprof} on my program, and it says: ``bad format''.}
@ans{} @samp{Gprof} from DJGPP v2.0 needs the original COFF file the
linker produced. If you delete it, or feed @samp{Gprof} with the
@file{.exe} file instead, it will be most unhappy. The way to produce
the COFF output is explained in @ref{GDB needs COFF, section dealing
with GDB, How to produce a COFF image}, above. Alternatively, upgrade
to DJGPP v2.01, where all Binutils programs know about .exe
executables.
@node Gprof docs, IO bound programs, Gprof needs COFF, Profiling
@comment node-name, next, previous, up
@section Where is Gprof docs?
@cindex Documentation, the profiler
@cindex Profiler documentation
@pindex Gprof documentation
@quest{What about all those @samp{Gprof} options? Where can I find
their docs?}
@quest{I can't figure out some of the info in the @samp{Gprof} report @dots{}}
@ans{} @samp{Gprof} documentation, @file{gprof.inf}, was accidentally
left out of the Binutils binary distribution, @file{bnu27b.zip} in DJGPP
v2.01. If you don't have @file{gprof.inf} in your info subdirectory,
you will have to look for it in the @ftp{latest Binutils source
distribution,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2gnu/bnu@value{bnu-version}s.zip}.
@node IO bound programs, No profile, Gprof docs, Profiling
@comment node-name, next, previous, up
@section Why is @code{__dpmi_int} so heavily used?
@cindex Profiling, library routines
@cindex __dpmi_int, high in program's profile
@quest{I've profiled my program and found that the routine which takes
60% of the running time is some obscure library function called
@code{__dpmi_int.} Can't you guys make your library right?}
@ans{} 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 @code{__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.
@node No profile, , IO bound programs, Profiling
@comment node-name, next, previous, up
@section @samp{gprof} doesn't produce output
@cindex Profiler produces no output
@cindex Profiling programs that terminate abnormally
@cindex Programs that exit abnormally, how to profile
@pindex gprof produces no output
@quest{Every time I run the profiler it says ``gmon.out: no such file or
directory'' and no profile is produced. What is this @file{gmon.out}
and why won't @samp{gprof} compute the profile?}
@ans{} @file{gmon.out} is the file with raw execution counts and timing
info that @samp{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:
@itemize @bullet{}
@item
You didn't compile and/or link your program with the @samp{-pg} switch.
Note that @strong{both} compilation and link need to be done with
@samp{-pg}, because the functions that actually write the results to
@file{gmon.out} are only linked in when @samp{gcc} sees @samp{-pg} on
the link command line.
@item
You have called @file{ld.exe} directly to link your program and forgot
to mention the files and switches necessary for the profiled program
operation. You should use @samp{gcc} to link your program instead of
calling the linker directly; a @samp{-pg} switch to @samp{gcc} is all
that it takes to make sure that the linker will get all the necessary
arguments@footnote{
If you absolutely need to call @file{ld.exe} directly, invoke @samp{gcc}
once with a @samp{-v} switch and you will see what are the arguments
that you should pass to the linker in your case.}.
@item
Your program exited abnormally. The function which generates
@file{gmon.out} is registered with the @code{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 @code{exit} library
function or with a @code{return} statement in your @code{main} function.
For example, if your program dies with an exception or a signal, install
a signal handler and make it call @code{exit.}
@end itemize
@node Performance, Memory, Profiling, Top
@comment node-name, next, previous, up
@chapter Run-time Performance of DJGPP Programs
@cindex Performance issues
@cindex Run-time performance
This chapter deals with issues pertinent to run-time performance of
DJGPP programs.
@menu
* How fast:: What code quality should you expect.
* Older is faster:: Are older versions faster than newer ones?
* Pentium:: DJGPP programs on a Pentium.
* IO speed:: Is I/O @emph{really} so slow in protected mode?
* Slow-down:: What if your ported program runs slower?
@end menu
@node How fast, Older is faster, Performance, Performance
@comment node-name, next, previous, up
@section How efficient is DJGPP-generated code?
@cindex Code quality, GCC
@cindex Mode switches, effect on program speed
@pindex GCC, code efficiency
@quest{How does DJGPP compare with other DOS-based C compilers in terms of
efficiency of generated code?}
@quest{Won't my program run @strong{much} slower when compiled by
DJGPP, due to all those CPU cycles wasted in switches between protected
and real mode?}
@ans{} The quality of code generated by GCC with optimization turned on
(@samp{-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.
@node Older is faster, Pentium, How fast, Performance
@comment node-name, next, previous, up
@section Comparing newer versions with old ones
@cindex Code speed, slower in v2.x
@cindex v2 code slower than v1.x
@cindex v2.01 code slower than v2.0
@cindex Runtime speed, slower in v2.x
@cindex Binutils 2.8.x, slower than 2.7
@cindex Optimization, GCC switches
@cindex Speed of code, recommended GCC switches
@cindex Stack, misalignment causes slow-down
@quest{I switched to v2 and my programs now run slower than when
compiled with v1.x@dots{}}
@quest{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?}
@quest{I installed Binutils 2.8.1, and my programs are now much slower
than when they are linked with Binutils 2.7!}
@ans{} 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, @samp{--force-mem} is switched on by
@samp{-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:
@itemize @bullet{}
@item
Compile your code using the GCC switches @samp{-O2 -mpentium
-fomit-frame-pointer -ffast-math}. (For PGCC use @samp{-O6} instead of
@samp{-O2}.) Omit @samp{-ffast-math} if you link with @samp{-lm} and
need the @code{errno} variable to be set or the @code{matherr} function
to be called in case of errors.
@item
Profile your code and check which functions are ``hot spots''.
Disassemble them, or compile with @samp{-S} (@pxref{Assembly output,
getting assembly listing, How to get GCC to generate assembly listing}),
and examine the machine code.
@item
If the disassembly shows there aren't too many memory accesses inside
the inner loops, try adding @samp{-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
@samp{-fno-force-mem}, to prevent GCC from repeatedly copying variables
from memory into registers.
@item
Try adding @samp{-funroll-loops} and @samp{-funroll-all-loops} and
profile the effect.
@item
Try compiling with @samp{-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.
@item
Sometimes, @samp{-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.
@item
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.
@end itemize
@pindex PGCC, bugs with optimization levels -O7 and higher
@cindex Optimization bugs, in PGCC with -O7 and higher
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.
@paragraph{}
@cindex Arrays, and code speed
@cindex Speed of array-based programs
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.
@paragraph{}
Another problem that is related to C@t{++} programs which manipulate
arrays happens when you fail to qualify the methods used for array
manipulation as @code{inline}. Each method or function that wasn't
declared @code{inline} will @emph{not} be inlined by GCC, and will incur
an overhead of function call at run time.
@paragraph{}
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.
@paragraph{}
@cindex STUB, environment variable
@cindex Alternate stub, how to use
@cindex Stub, how to use non-default one
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 @code{stubify} utility and
point the @code{STUB} environment variable to a program with a new
stub.)
@node Pentium, IO speed, Older is faster, Performance
@comment node-name, next, previous, up
@section DJGPP programs on a Pentium
@cindex Alignment of data by GAS can slow-down code
@cindex Code is slow due to incorrect alignment by GAS
@cindex Slow code, due to bad alignment by GAS
@cindex Pentium-optimized code
@quest{Does DJGPP support Pentium-specific optimizations?}
@quest{I run the same program on a 486 and on a Pentium, and it's slower
on a Pentium!!}
@ans{} 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.
@paragraph{}
@pindex PGCC
@pindex EGCS, a DJGPP port
Lately, the FSF has split the GCC development into two branches: one is
the regular GCC, while the other is called EGCS@footnote{ Pronounced
like ``eggs''.}, the @dfn{Experimental GNU Compiler System}. The latter
is usually less stable than the GCC releases, but supports more advanced
features, like the so-called @dfn{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 @mail{Andrew Crabtree,
andrewc@@rosemail.rose.hp.com}, and can be downloaded from the @www{PCG
site, www.goof.com/pcg/}.
@paragraph{}
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.
@paragraph{}
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.
@node IO speed, Slow-down, Pentium, Performance
@comment node-name, next, previous, up
@section My program's I/O is so slow!
@cindex I/O speed, DJGPP programs
@cindex Buffered I/O, effect of buffer size on I/O speed
@cindex setvbuf, effect on I/O speed
@pindex GCC, I/O speed
@quest{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 @strong{horribly} slow: its 25% slower
than Borland!}
@quest{I tried to improve DJGPP I/O throughput by defining a 64KB-large
buffer for buffered I/O with a call to @code{setvbuf}, but that had no
effect. Why is that?}
@quest{It is obvious that disk-bound programs compiled with DJGPP will
run @strong{awfully} slow, since FAT is such a lousy filesystem!}
@ans{} First, I would like to point out that waiting another
0.5@dmn{sec} 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@dots{} Besides, most programs read and write files which are
only a few hundreds of kilobytes, and those will suffer only a
negligible slow-down.
@paragraph{}
@cindex Transfer buffer, what it is
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 @dfn{transfer buffer}@footnote{
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.
@paragraph{}
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.}. 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@footnote{
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 @code{stubedit} with a @samp{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
@code{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.}, so if your program really reads a lot
of large files, you might be better off enlarging it (with the
@samp{STUBEDIT} program).
@paragraph{}
@cindex File I/O, compared with Linux
@cindex Disk I/O, compared with Linux
Some people think that FAT is such a lousy filesystem, that programs
which do a lot of disk I/O @emph{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.
@paragraph{}
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.
@node Slow-down, , IO speed, Performance
@comment node-name, next, previous, up
@section My ported program runs much slower!
@cindex Slow-down, programs ported from other compilers
@cindex Ported programs run much slower
@cindex FPU emulation slows down programs
@cindex Slow-down, when resident software uses XMS
@pindex Novell VLM causes slow-down of DJGPP programs
@quest{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? }
@ans{} Explore the following possible causes for this:
@enumerate a
@item
Your program extensively calls services other than I/O which require mode
switch (like BIOS Int 10h, mouse services, etc.).
@paragraph{}
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 @code{__dpmi_int} (which
calls real-mode DOS/BIOS services) and @code{__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).
@paragraph{}
@item
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 @code{__djgpp_exception_processor} is high on the execution
profile printed by @samp{Gprof}. Due to the way FP emulation is
implemented in DJGPP@footnote{
Without a real x87 FPU, an exception is generated by the CPU each time a
floating-point instruction is seen in the code.
@code{__djgpp_exception_processor} is called for each such exception and
services it by calling the emulator, @samp{emu387.dxe}, or functions
from the emulator library @file{libemu.a} (if the program was linked
with @samp{-lemu}), to emulate the instruction. Since exception
processing incurs a lot of overhead, this emulation is slow.}, 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.
@paragraph{}
@item
Your program uses library functions/classes which are implemented less
efficiently by DJGPP libc and the GNU C@t{++} 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 @samp{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
@news{comp.os.msdos.djgpp}, so this could be fixed by people who
maintain the library.
@paragraph{}
@item
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
@ref{Older is faster, speed-related optimization options, Comparing
newer versions with old ones}.
@paragraph{}
@item
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.
@paragraph{}
@item
If the slow program was compiled for profiling (with he @samp{-pg}
switch), the slow-down might be due to a bug in he DJGPP library.
@xref{Profiled crash, slow-down in profiled programs, Programs compiled
with -pg crash when run}, for more about this.
@paragraph{}
@item
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.
@end enumerate
@node Memory, Command line, Performance, Top
@comment node-name, next, previous, up
@chapter Run-Time Memory Issues
@cindex Memory at run time
@cindex Virtual memory
This chapter answers questions which are related to DJGPP run-time
memory allocation.
@menu
* How much memory:: How much can you use?
* Confusing alloc:: Allocation mechanism peculiarities.
* QDPMI VM:: QDPMI doesn't provide virtual memory.
* QDPMI alloc:: QDPMI/Windows 9X memory allocation peculiarities.
* Windows alloc:: VM issues under Windows 3.X.
* Windows9X alloc:: VM peculiarities under Windows 9X.
* EMM386 alloc:: Some versions of EMM386 are limited to 32 MBytes.
* Swap out:: How much VM do spawned program have?
* Stack size:: How large is the stack and how to enlarge it?
@end menu
@node How much memory, Confusing alloc, Memory, Memory
@comment node-name, next, previous, up
@section How much virtual memory do you have?
@cindex Virtual memory, maximum available
@cindex Memory, virtual, maximum available
@pindex CWSDPMI, maximum available virtual memory
@quest{How much virtual memory can I use in DJGPP programs?}
@ans{} 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 @code{malloc(50*1024*1024)} some day.
@paragraph{}
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 @ref{QDPMI VM, QDPMI VM bug,
Failure to get more memory than is physically available}, 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 @file{.pif} file settings for
the program you run (see @ref{Windows alloc, Windows allocation
subtleties, Memory allocation fails under Windows}, below). Under
Windows 9X, the memory settings of the DOS Box Property Sheets define how
much virtual memory a DJGPP program will get (see @ref{Windows9X alloc,
Windows 9X allocation details, Memory allocation peculiarities under Windows
9X}, below). OS/2 reportedly can be configured to support up to 512MB
of DPMI memory.
@node Confusing alloc, QDPMI VM, How much memory, Memory
@comment node-name, next, previous, up
@section It seems @code{malloc}/@code{free} don't affect virtual memory@dots{}
@cindex Virtual memory, malloc doesn't change
@cindex Virtual memory, free doesn't change
@cindex Memory, virtual, malloc doesn't change
@cindex Memory, virtual, free doesn't change
@cindex malloc doesn't change virtual memory
@cindex free doesn't change virtual memory
@cindex __dpmi_get_memory_information, doesn't change after free/malloc
@cindex _go32_remaining_physical_memory, doesn't change after free/malloc
@quest{I did @code{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?}
@quest{I @code{malloc}'ed a large chunk of memory, but when I check
values returned by @code{_go32_remaining_physical_memory} or
@code{__dpmi_get_memory_information}, I don't see any change!}
@quest{When I @code{free} allocated RAM,
@code{_go32_remaining_physical_memory} reports there was no change in the
available RAM@dots{}}
@quest{I'm looking for a way to tell how much memory is available,
something like @code{coreleft} in Borland C?}
@ans{} CWSDPMI (and, possibly, other DPMI hosts) only pages in memory
when it is actually accessed. If you only @code{malloc} it, but don't
actually access it, it won't grab those pages. Try @code{calloc} and
see the @strong{big} difference.
@paragraph{}
When you call @code{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''.
@paragraph{}
@cindex _go32_remaining_physical_memory, under OS/2
@pindex OS/2, and _go32_remaining_physical_memory
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
@code{_go32_remaining_physical_memory} reports a constant very big value
that doesn't change in the course of the program.
@paragraph{}
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 @code{_go32_remaining_physical_memory} library
function at program startup, and then track memory usage with
@code{sbrk(0);}. Alternatively, disabling virtual memory altogether (by
using CWSDPR0 or by loading CWSDPMI with @samp{-s-} parameter), and
checking values returned by @code{malloc} against @code{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
@emph{virtual} memory should call @code{_go32_remaining_virtual_memory}
instead.
@node QDPMI VM, QDPMI alloc, Confusing alloc, Memory
@comment node-name, next, previous, up
@section Failure to get more memory than is physically installed
@cindex Virtual memory, QDPMI failure
@cindex Memory, virtual, QDPMI failure
@cindex Virtual memory, failure to allocate
@cindex Memory, virtual, failure to allocate
@cindex sbrk algorithm and QDPMI
@cindex _crt0_startup_flags settings and QDPMI
@pindex QDPMI fails to provide virtual memory
@pindex QDPMI and _crt0_startup_flags settings
@pindex 386Max, how to ensure virtual memory
@pindex 386Max, speeding up DJGPP start-up
@quest{When I try to access more memory than the free physical RAM,
@code{malloc} returns a @code{NULL} pointer, or I get some cryptic error
message, like ``Memory Paging Violation'' or ``Unrecoverable Exception:
000Eh''.}
@ans{} 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 @ref{Old QDPMI, virtual
memory with QEMM, You need QEMM 7.53 or later}, and use CWSDPMI instead.
@paragraph{}
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 @code{sbrk} behavior by setting
@code{_crt0_startup_flags} to @code{_CRT0_FLAG_UNIX_SBRK} (QEMM 8.0 and
later can allocate virtual memory with both types of @code{sbrk}
algorithm).
@paragraph{}
If you use another DPMI host, make sure that virtual memory is enabled.
E.g., for 386Max, include the @samp{swapfile=} parameter to establish a
virtual memory swap file; you can make it permanent (this will speed up
DJGPP start-up) with the @samp{/p} option.
@node QDPMI alloc, Windows alloc, QDPMI VM, Memory
@comment node-name, next, previous, up
@section Memory allocation fails before all memory is used
@cindex Memory allocation fails under QDPMI or Windows 9X
@cindex malloc fails under QDPMI or Windows
@cindex calloc fails under QDPMI or Windows
@cindex Program crashes while allocating memory
@pindex QDPMI, malloc/calloc failure
@pindex Windows, malloc/calloc failure
@quest{OK, I've changed my program to never allocate more memory than is
physically available, to work around that QDPMI VM bug, described in
@ref{QDPMI VM, previous section, Failure to get more memory than is
physically available}, but my program still gets a @code{NULL} pointer
from @code{malloc/calloc}!}
@quest{Why is my program dying with SIGSEGV under CWSDPMI when
allocating a chunk of memory?}
@ans{} 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.
@paragraph{}
With some DPMI providers, this behavior might be triggered by a small
overhead of each @code{malloc} call: you might ask for half of available
memory, but the DJGPP implementation of @code{malloc} adds the overhead
and then rounds the amount of memory to the next power of 2 before
calling @code{sbrk}; thus @code{malloc(8MB)} will actually request
16MBytes from the DPMI host. When in doubt, call @code{sbrk} directly,
especially if you don't plan to free that memory during execution.
@paragraph{}
@cindex Memory allocation in small chunks fails
@cindex malloc in small chunks fails
@pindex CWSDPMI crashes programs allocating memory is small chunks
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.
@node Windows alloc, Windows9X alloc, QDPMI alloc, Memory
@comment node-name, next, previous, up
@section Memory allocation fails under Windows
@cindex Memory allocation fails under Windows 3.X
@cindex malloc fails under Windows 3.X
@cindex calloc fails under Windows 3.X
@pindex Windows 3.X, malloc/calloc fails
@quest{I'm running under Windows 3.X DOS box, but DJGPP complains about
there not being enough DPMI memory, although virtual memory is enabled.}
@ans{} 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
@example
PageOverCommit=n
@end example
@noindent
in the @samp{[386Enh]} section of your @file{SYSTEM.INI} file. The
parameter @samp{n} is 4 by default, but can be set to be as large as 20.
@node Windows9X alloc, EMM386 alloc, Windows alloc, Memory
@comment node-name, next, previous, up
@section Memory allocation peculiarities under Windows 9X
@cindex Memory allocation fails under Windows 9X
@cindex malloc fails under Windows 9X
@cindex calloc fails under Windows 9X
@cindex Virtual memory under Windows 9X
@pindex Windows 9X doesn't allow more than 16MB virtual memory
@quest{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@dots{}}
@ans{} You must set the maximum amount of DPMI memory to 65535K in the
DOS applications' Property Sheets. Click on the @samp{Properties}
button of the DOS box toolbar, then click on the @samp{Memory} tab, and
type the number @samp{65535} in the box under @samp{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).
@paragraph{}
If you have more than 64MB of physical memory installed, you can specify
the amount of memory on the @code{EMM386} command line in your
@file{CONFIG.SYS}, like this:
@example
DEVICE=C:\WINDOWS\EMM386.EXE NOEMS L=131072
@end example
@noindent
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.
@paragraph{}
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.
@node EMM386 alloc, Swap out, Windows9X alloc, Memory
@comment node-name, next, previous, up
@section Memory allocation fails under EMM386 or HIMEM
@cindex Memory allocation fails under EMM386 or HIMEM
@cindex malloc fails under EMM386 or HIMEM
@cindex calloc fails under EMM386 or HIMEM
@cindex Paging starts before all RAM is used
@pindex EMM386, cannot use all free memory
@pindex EMM386, malloc/calloc fails
@pindex HIMEM, malloc/calloc fails
@pindex CWSDPMI, pages too early under EMM386
@pindex go32-v2, use to find out how much memory is available to DJGPP
@quest{My machine has 48 MBytes of RAM, but when I run DJGPP programs,
they start paging after 32 MBytes have been used@dots{}}
@quest{I have 5 MBytes of free RAM on my machine, but DJGPP programs start
paging after only 256KBytes of memory were used??}
@ans{} 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.
@paragraph{}
If your programs start paging after only 256KBytes of memory were used,
most probably you are using EMM386 and CWSDPMI, and your
@file{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
@samp{go32-v2} program to see what amount of extended memory your DJGPP
programs will get.
@node Swap out, Stack size, EMM386 alloc, Memory
@comment node-name, next, previous, up
@section How much memory do parent DJGPP programs leave for their child?
@cindex Child programs, how much memory is left
@cindex Nested programs, how much memory is left
@cindex Spawned programs, how much memory is left
@cindex Subsidiary programs, how much memory is left
@cindex Memory, how much is left for spawned programs
@cindex No free XMS memory when NOEMS parameter is used
@pindex QDPMI, memory usage for nested programs
@pindex CWSDPMI, memory usage for nested programs
@pindex Windows, memory usage for nested programs
@pindex STUBEDIT, effect on memory left to spawned programs
@quest{How much memory is available when I call the @code{system}
library function?}
@ans{} 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 @code{system} (like in recursive
invocation of @samp{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 @code{STUBEDIT}), the amount of free conventional RAM left when
shelling out of it will change accordingly.
@paragraph{}
Extended memory management is left to the DPMI server; DJGPP does
nothing special about XMS when @code{system} is called. This means that
all the extended memory used by the parent program is @strong{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
@code{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.
@paragraph{}
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.
@node Stack size, , Swap out, Memory
@comment node-name, next, previous, up
@section How much stack can I have in DJGPP programs?
@cindex Stack size under DJGPP
@cindex Automatic variables, how much memory
@cindex _stklen, setting stack size
@cindex Programs crash with SIGSEGV due to small stack size
@cindex Stack size, insufficient, causes programs to crash
@cindex Stack overflow under debugger
@cindex Debugger causes programs to overflow the stack
@cindex C@t{++} compiler crashes for large programs
@pindex CC1PLUS crashes with SIGSEGV
@pindex STUBEDIT, changing stack size
@pindex Windows, stack size control
@pindex BCCBGI (from BCC2GRX) crashes with the default stack
@pindex GDB causes stack overflow in a debuggee
@quest{My program bombs when I use very large automatic arrays.}
@quest{How much stack space do I have in my program?}
@quest{My program seems to overflow the stack, but only when I run it
under a debugger@dots{}}
@quest{My program crashes with SIGSEGV, but the traceback makes no
sense: it points to something called ___djgpp_exception_table@dots{}
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??}
@ans{} 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
@samp{STUBEDIT} program (change the parameter ``Minimum amount of stack
space''), or by setting the global variable @code{_stklen} in your
program. Example:
@smallexample
unsigned _stklen = 1048576; /* need a 1MB stack */
@end smallexample
The DJGPP startup code checks both the value in the stub info and the
value of @code{_stklen}, and uses the larger of these two. Therefore,
programs that are known to require large stack size should set
@code{_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 @code{gdb} (see below). However, you
might need to use @samp{STUBEDIT} with programs for which you don't have
the sources.
@paragraph{}
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
@samp{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
@code{_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.)
@paragraph{}
Some users have reported that they needed to enlarge the stack size of
the C@t{++} compiler, @file{cc1plus.exe}, to prevent it from crashing when
compiling some exceedingly large and complex C@t{++} programs. Another
program that was reported to need a stack larger than the default is
@file{bccbgi.exe} from the @samp{BCC2GRX} package.
@paragraph{}
After you've used @samp{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 @samp{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).
@paragraph{}
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 @code{_stklen}.
@paragraph{}
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 @file{.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 @file{.PIF} file for this program? Then Windows uses the default file
@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.
@paragraph{}
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.
@node Command line, Converting, Memory, Top
@comment node-name, next, previous, up
@chapter Command-line Arguments Handling in DJGPP
@cindex Command-line arguments
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.
@menu
* Filename globbing:: Wildcard expansion under DJGPP
* Disable globbing:: You can disable globbing if you don't need it.
* Special chars:: How to pass arguments with special chars.
* Long commands:: DJGPP can pass very long command lines.
* How long:: Look here to find out how long.
* Makefiles:: Makefiles can disable long command lines.
@end menu
@node Filename globbing, Disable globbing, Command line, Command line
@comment node-name, next, previous, up
@section Filename wildcards expansion under DJGPP
@cindex Wildcards expansion
@cindex Filename wildcards expansion
@cindex Filename globbing
@cindex Globbing in filenames
@cindex Command line, filename expansion/globbing
@cindex Command line, * and ? characters
@cindex * character in command lines
@cindex ? character in command lines
@quest{Can I do filename globbing with DJGPP?}
@quest{I call my program with an argument @samp{x*y} and it complains
about something called @samp{xyzzy}??@dots{}}
@quest{I cannot find a way to use the @samp{/?} switch with my
programs!}
@ans{} The filename globbing in DJGPP is done by the start-up code,
before your @code{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 @samp{x*y} above was expanded to a file called
@file{xyzzy} which was probably present in the current working
directory; and @samp{/?} 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
@ref{Disable globbing, how to disable globbing, How to disable filename
wildcard expansion}.)
@paragraph{}
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:
@table @samp
@titem ?
any single character.
@titem *
zero or more arbitrary characters, including a dot `.'
@titem [aA_]
any one of characters `a', `A', or `_'.
@titem [a-d]
any one of characters `a', `b', `c', or `d'.
@titem [!a-z]
anything @emph{but} a lowercase letter.
@titem ...
all the subdirectories, recursively (VMS aficionados, rejoice!).
@titem .../*
all the files in all subdirectories, recursively.
@end table
Unlike DOS, the @samp{*} and @samp{?} meta-characters can appear
@emph{anywhere} in the filename pattern, like in @samp{[a-z]*[0-9].*pp.}
You can also use @samp{*} instead of directories, like in
@samp{*/*/*.c}, but @strong{not} on drive letters (e.g., @samp{[a-c]:/}
won't work).
@paragraph{}
Note that @samp{*.*} only picks up files that actually have an
extension. This is contrary to the usual DOS practice where it means
@emph{all} the files, with or without extension.
@paragraph{}
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
@samp{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 (@samp{sh}, @samp{ksh}, and @samp{bash}).
@paragraph{}
@cindex Globbing and file name letter-case
@cindex Case-sensitivity, while expanding wildcards
@cindex Wildcards, and letter-case in file names
@cindex FNCASE variable and wildcard expansion
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, @samp{[A-D]*} will @strong{not}
match a file called @file{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 @code{FNCASE} is set to @samp{y}. The effect
of setting @code{FNCASE} is fully described in the @cite{DJGPP C Library
reference}, under the @code{_preserve_fncase} function; type @kbd{info
libc alpha _preserve_fncase} from the DOS prompt.
@node Disable globbing, Special chars, Filename globbing, Command line
@comment node-name, next, previous, up
@section How to disable filename wildcards expansion
@cindex Wildcards expansion, disabling
@cindex Disabling wildcard expansion
@cindex Disabling globbing in filenames
@cindex Filename wildcards, disabling expansion
@cindex Filename globbing, disabling
@cindex Globbing in filenames, disabling
@cindex Command line, disabling filename expansion/globbing
@cindex __crt0_glob_function, disable filename globbing
@quest{OK, but I don't want my program to glob its arguments (they
aren't files at all, but they include characters like @samp{*} and
@samp{?}). What should I do?}
@ans{} You have these alternatives:
@itemize @bullet{}
@item
Surround your arguments with single or double quotes (this is what you
would do under a Unix shell).
@item
Disable globbing for your program by linking it with your custom version
of the function with the special name @code{__crt0_glob_function} and make
it always return a @code{NULL} pointer. See the documentation of this
function in the library reference, for more details. Here's an example:
@example
char **__crt0_glob_function (char *arg)
@{
return 0;
@}
@end example
@end itemize
@node Special chars, Long commands, Disable globbing, Command line
@comment node-name, next, previous, up
@section How to pass command-line arguments with quotes or @samp{@@}
@cindex Quotes, how to pass them to programs
@cindex @@ character, how to pass it to programs
@cindex Command line, escaping special characters
@quest{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 @dots{}}
@quest{How do I pass a command-line argument which contains double
quotes? }
@quest{How do I pass an argument which begins with the @samp{@@}
character?}
@ans{} These special characters on the command-line arguments are
handled by the filename expansion (``globbing'') code before they are
passed to the @code{main} function (@pxref{Filename globbing,
description of filename expansion, How to disable filename wildcards
expansion}), 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 @file{myfile.c'v}, type it as
@samp{myfile.c@bs{}'v} when you call your program. If you have single
quotes in your program arguments @emph{and} you don't want those
arguments to be expanded, then surround them by double quotes, like
this: @samp{"*.c'v".} The program will get the string @samp{*.c'v} with
the double quotes stripped away.
@paragraph{}
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.
@paragraph{}
The @samp{@@} character serves to signal a @dfn{response file}
(@pxref{Long commands, the description of response file method, How to
pass command lines longer than 126 characters}), so it's also special.
To pass an argument whose first character is @samp{@@}, 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.
@paragraph{}
@cindex Whitespace in wildcards
@cindex Wildcards, and whitespace in file names
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
@w{@samp{c:/Prog*' 'F*}} (which should expand into @w{@file{c:/Program
Files}}) and @samp{*.c"'"v} (which should expand into all files with the
@file{*.c'v} extension).
@node Long commands, How long, Special chars, Command line
@comment node-name, next, previous, up
@section How to pass command lines longer than 126 characters
@cindex Long command lines
@cindex Makefiles with long command lines
@cindex !proxy method of passing long command lines
@cindex Command lines, longer than 126 characters
@cindex Response file, passing long command lines
@quest{Can I invoke my program with a command line longer than the
infamous DOS 126-character limit?}
@quest{I have a Makefile of Unix origin which contains some
@strong{very} long command lines. Will it work with DJGPP?}
@ans{} 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:
@itemize @bullet{}
@item
The @samp{!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.
@paragraph{}
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
@code{system}, @code{spawnXX} and @code{execXX} on the parent program
side, and by the start-up code on the child side@footnote{
In case you wonder, the name @samp{!proxy} comes from the string
which identifies the use of this method: instead of getting the actual
command line, the program gets @samp{!proxy} followed by the address of
the actual command line.}.
@paragraph{}
@item
The environment method. This is the same as the @samp{!proxy} method
above, but the information about the long command line is stored in an
environment variable called ``@t{ !proxy}'' (with the leading blank
and in lower-case). The reason for two similar, but different methods
is that command-line arguments passed by @code{system} library functions
should be globbed by the child, while the arguments passed by
@code{spawnXX} and @code{execXX} family of functions should not; thus
the former uses the environment method while the latter use the
@samp{!proxy} method.
@paragraph{}
@item
The response file method. Any argument which starts with a @samp{@@}
character (like in @samp{myprog @@file}) will cause the named @samp{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 @samp{Gawk} or @sc{sed} without
@samp{-f} option).
@paragraph{}
Note that this method makes @samp{@@} 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 (@pxref{Special chars,
how to pass the @b{@@} character, How to pass command-line arguments
with quotes or @samp{@@}}).
@end itemize
Of course, if the start-up code doesn't see any of the above methods, it
will use the command line by default.
@paragraph{}
@cindex @t{system} function doesn't call COMMAND.COM
Since the long command lines are a very important feature, DJGPP's
version of the @code{system} library function avoids calling the DOS
command processor, @file{COMMAND.COM}, unless it needs to run a batch
file or an internal command of @file{COMMAND.COM}. Other features of
the command processor, like redirection and pipes, are emulated
internally by @code{system}. See the library reference for
@code{system}, for more details about its extended functionality.
@node How long, Makefiles, Long commands, Command line
@comment node-name, next, previous, up
@section What is the maximum length of command line under DJGPP
@cindex Long command lines, maximum length
@cindex Length of command line
@cindex Maximum length of command line
@cindex Environment size affects spawning child programs
@cindex Spawning programs, effect of environment size
@pindex Make, maximum length of command line to pass to GCC
@pindex GCC, maximum length of command line in Makefiles
@quest{What is the longest command line I can pass to gcc when it is
invoked by @samp{Make}?}
@ans{} 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 @samp{!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 @emph{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.
@paragraph{}
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 @emph{parent program}
before you pass extremely long command lines to its children. GCC is
the first program you should worry about, because the linker
(@file{ld.exe}) usually gets long command lines from GCC (they include
the list of all the object files and libraries to be linked).
@node Makefiles, , How long, Command line
@comment node-name, next, previous, up
@section Why Make passes only 126 characters to programs?
@cindex Long command lines, from Makefile
@cindex Makefile, passing long command lines
@cindex SHELL= variable in Makefile, effect on long command lines
@cindex Redirection in Makefile, effect on long command lines
@cindex Redirection, using the REDIR program
@pindex Make, passing long command lines via Makefile
@pindex GCC, passing long command lines via Makefile
@pindex REDIR, use to get redirection and long command lines
@quest{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
@samp{!proxy} method?}
@quest{I use @sc{rhide}, but it only passes the first 126 characters of
my long command lines to the compiler!}
@ans{} If you use Make 3.73, check your Makefile for @code{SHELL =
command.com} statements, or for commands which include pipe or
redirection characters like @samp{>}, @samp{|}, etc. If Make sees any
such statements, it will invoke @file{COMMAND.COM} to run GCC, and
@file{COMMAND.COM} can't pass more than 126 characters to GCC. To work
around, comment-out the @code{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
@samp{redir} program which comes with DJGPP. For example, the following
command:
@example
frobnicate foo.bar > myfile.tmp
@end example
can be re-written instead like this:
@example
redir -o myfile.tmp frobnicate foo.bar
@end example
The ports of Make 3.75 and later doesn't call @file{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).
@paragraph{}
@cindex Long command lines, problems with RHIDE
@pindex RHIDE, long command lines
Problems with passing long commands from @sc{rhide} are usually caused
by invoking old programs compiled with DJGPP v2.0. Upgrade to the
latest binaries.
@node Converting, Low-level, Command line, Top
@comment node-name, next, previous, up
@chapter Converting DOS Programs/Libraries to DJGPP
@cindex Converting DOS code to DJGPP
@cindex DOS programs, converting to DJGPP
@cindex Libraries, converting 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.
@menu
* Syntax:: The (AT&T) syntax of Gas is different.
* Converting ASM:: Automated conversion tool.
* ASM GPF:: When converted code crashes.
* ASM and C:: Rules for assembly code called from C.
* OBJ and LIB:: You can't use them with GCC@dots{}
* 16-bit code:: @dots{}or can you?
* NEAR and FAR:: How to convert these to DJGPP.
* Pseudo-registers:: Converting _AX to DJGPP code.
@end menu
@node Syntax, Converting ASM, Converting, Converting
@comment node-name, next, previous, up
@section GCC/Gas won't accept valid assembly code @dots{}
@cindex Assembly source, GCC/Gas syntax
@cindex AT&T vs Intel assembly syntax
@cindex Intel vs AT&T assembly syntax
@cindex Assembly syntax
@cindex Tutorials on AT&T syntax and NASM
@pindex NASM, a tutorial on usage with DJGPP
@quest{I have some code written in assembly which compiles under
@sc{masm} and @sc{tasm}, but GCC gives me a long list of error
messages.}
@ans{} The GNU Assembler (@file{as.exe}), or @samp{Gas}, called by GCC
accepts the @dfn{AT&T syntax}, which is different from the @dfn{Intel
syntax}. Notable differences between the two syntaxes are:
@itemize @bullet{}
@item
AT&T immediate operands are preceded by @code{$}; Intel immediate operands
are undelimited (Intel @code{push 4} is AT&T @code{pushl $4}).
@item
AT&T register operands are preceded by @code{%}; Intel register operands
are undelimited. AT&T absolute (as opposed to PC-relative)
@code{jump}/@code{call} operands are prefixed by @code{*}; they are
undelimited in Intel syntax.
@item
AT&T and Intel syntax use the opposite order for source and destination
operands. Intel @code{@w{add eax, 4}} is @code{@w{addl $4, %eax}} in
AT&T syntax.
The @code{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.
@item
In AT&T syntax, the size of memory operands is determined from the
last character of the opcode name. Opcode suffixes of @code{b},
@code{w}, and @code{l} specify byte (8-bit), word (16-bit), and long
(32-bit) memory references. Intel syntax accomplishes this by prefixing
memory operands (@emph{not} the opcodes themselves) with @code{`byte
ptr'}, @code{`word ptr'}, and @code{`dword ptr'.} Thus, Intel
@code{@w{mov al, byte ptr FOO}} is @code{@w{movb FOO, %al}} in AT&T
syntax.
@item
Immediate form long jumps and calls are
@code{@w{lcall/ljmp $SECTION, $OFFSET}} in AT&T syntax; the Intel syntax
is @code{@w{call/jmp far SECTION:OFFSET}.} Also, the far return
instruction is @code{@w{lret $STACK-ADJUST}} in AT&T syntax; Intel syntax
is @code{@w{ret far STACK-ADJUST}.}
@item
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.
@c
@c ... Insert reminder than you don't need separate segments under
@c DJGPP?
@c
@item
An Intel syntax indirect memory reference of the form
@example
SECTION:[BASE + INDEX*SCALE + DISP]
@end example
is translated into the AT&T syntax
@example
SECTION:DISP(BASE, INDEX, SCALE)
@end example
@end itemize
Examples:
@example
@strong{Intel:} [ebp - 4] @strong{AT&T:} -4(%ebp)
@strong{Intel:} [foo + eax*4] @strong{AT&T:} foo(,%eax,4)
@strong{Intel:} [foo] @strong{AT&T:} foo(,1)
@strong{Intel:} gs:foo @strong{AT&T:} %gs:foo
@end example
For a complete description of the differences,
@extref{i386-Dependent, i386-dependent features, as, GNU assembler
documentation,
www.delorie.com/gnu/docs/binutils-2.7/as_164.html#SEC192}. If you don't
read this FAQ with an Info browser, download @ftp{GNU Binutils,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2gnu/bnu@value{bnu-version}b.zip},
unzip the files named @file{as.iN} (where @file{N} is a digit) from
it, then type at the DOS prompt:
@example
info as machine i386
@end example
You will see a menu of @samp{Gas} features specific to x86 architecture.
@paragraph{}
A guide is available which was written by @mail{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 @www{DJGPP inline assembly tutorial,
brennan.home.ml.org/djgpp/djgpp-asm.html}.
Another useful tutorial about writing separate assembly-language modules
for DJGPP was written by @mail{George Foot,
george.foot@@merton.oxford.ac.uk} and is available from @www{George's
home page, users.ox.ac.uk/~mert0407/asmfuncs.txt}.
The DJGPP User's Guide also has a @www{tutorial on writing
assembly-language code, 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 @ftp{@sc{nasm},
@SimTel{}/pub/simtelnet/msdos/asmutl/nasm@value{nasm-version}.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 @sc{nasm} with DJGPP was written by @mail{Matthew Mastracci,
mmastrac@@acs.ucalgary.ca} and is available from @www{Matthew's Web
page, www.acs.ucalgary.ca/~mmastrac/files/djgppasm.html}.
@node Converting ASM, ASM GPF, Syntax, Converting
@comment node-name, next, previous, up
@section Converting between Intel ASM syntax and AT&T syntax
@cindex Assembly source, converting to AT&T syntax
@cindex Intel-style assembly code, using with DJGPP
@pindex Sed script to convert ASM to AT&T syntax
@pindex TA2AS, a converter from Intel to AT&T assembly syntax
@pindex NASM, a portable assembler with Intel syntax support
@pindex JAS, a free assembler with Intel-like syntax
@quest{Where can I find an automated conversion tool to convert my
@samp{Intel}-style assembly code into a code acceptable by @samp{Gas}?}
@quest{Where can I find a converter from @samp{AT&T} assembly to
@samp{Intel} style?}
@ans{} A @sc{sed} script which should do most of the conversion was
posted to the @www{DJGPP news group,
www.delorie.com/djgpp/mail-archives/djgpp/1995/06/06/05:48:34}.
A program called @samp{TA2AS} which can convert @sc{tasm}
assembly source to AT&T style can be found @ftp{on the DJGPP server,
ftp.delorie.com/pub/djgpp/contrib/ta2asv08.zip} and @ftp{on
Oulu, x2ftp.oulu.fi/pub/msdos/programming/convert/ta2asv08.zip}.
@samp{TA2AS} was written by Frank van Dijk of the Spirit group; if you
have questions about this tool, you may contact @mail{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.
@paragraph{}
Alternatively, here is what you can do to make your code linkable with
DJGPP programs:
@itemize @bullet{}
@item
Get and install @sc{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. @sc{nasm} is free for non-commercial use (see the
docs for commercial use restrictions) and can be compiled with DJGPP.
@ftp{@sc{nasm} sources are on SimTel.NET,
@SimTel{}/pub/simtelnet/msdos/asmutl/nasm@value{nasm-version}s.zip}.
A pre-compiled MS-DOS executable binary of @sc{nasm} is available
@ftp{from SimTel.NET,
@SimTel{}/pub/simtelnet/msdos/asmutl/nasm@value{nasm-version}.zip}.
The author and maintainer of @sc{nasm} is @mail{Simon Tatham,
anakin@@pobox.com}.
@paragraph{}
Be warned that @sc{nasm} is @emph{not} 100% identical to @sc{masm} or
@sc{tasm}. Even experienced assembly programmers might need some time
to adapt to the slightly different flavor of @sc{nasm}. If you want
something much more similar to @sc{tasm}, get @sc{jas}. @sc{jas} is
available @ftp{from OULU,
x2ftp.oulu.fi/pub/msdos/programming/djgpp2/jas31.zip}.
@paragraph{}
@item
For a small number of relatively short files, consider converting them
with a smart editor (like Emacs or its work-alikes).
@paragraph{}
@item
Obtain a copy of Microsoft @sc{masm} 6.11. It has a @samp{-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 @samp{LIB32}
librarian from Microsoft C8 to convert object files to COFF by putting
them into a @file{.lib} library, then extracting them as COFF files.
@footnote{If you use @sc{masm} or @sc{lib32}, please post your
experiences to @news{comp.os.msdos.djgpp}, so that I can make the above
instructions less vague.}
@paragraph{}
@item
Use a disassembler to disassemble the object code, then convert it to
the AT&T format either by hand or using @samp{TA2AS}. One place to look
for such a disassembler is @ftp{on SimTel.NET mirrors,
@SimTel{}/pub/simtelnet/msdos/disasm/}.
@end itemize
@paragraph{}
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 (@pxref{ASM GPF,
next question, Converted code GP Faults!}).
@paragraph{}
@cindex Assembly source, converting from AT&T to Intel
@cindex AT&T-style assembly, converting to Intel
@pindex ATT2INTL, a converter from AT&T to Intel assembly
If you need to perform the opposite conversion, from the @samp{AT&T}
style to the @samp{Intel} style, try the @samp{Att2Intl} converter
written by @mail{Greg Velichansky, hmaon@@umiacs.umd.edu}. Its output
is intended for @sc{nasm} or @sc{tasm}. @samp{Att2Intl} is available
@www{from Greg's home page, www.wam.umd.edu/~gvelicha/a2i/}.
@node ASM GPF, ASM and C, Converting ASM, Converting
@comment node-name, next, previous, up
@section Converted code GP Faults!
@cindex Assembly source, converting to protected mode
@cindex Protected mode and converted assembly code
@quest{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 @sc{masm}, so
how can this be?}
@ans{} In DJGPP, your program runs in @strong{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.
@paragraph{}
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:
@itemize @bullet{}
@item
Loading arbitrary values into segment registers, then using them to
reference code or data.
@item
Referencing code with data segment register, or vice versa.
@item
Assuming certain locations (like BIOS area or video memory) will be found
at certain absolute addresses.
@item
Calling DOS or BIOS services with @code{INT NN} instruction.
@item
Hooking interrupts by poking absolute addresses.
@end itemize
@node ASM and C, OBJ and LIB, ASM GPF, Converting
@comment node-name, next, previous, up
@section Which registers need to be saved in assembly code?
@cindex Registers, which ones to save in assembly code
@cindex Assembly functions, which registers to save
@cindex Assembly code crashes when linked with optimized C code
@quest{Which register can I safely change in my assembly code that is
called from a C program?}
@quest{How come my program crashes with a GPF, but only if I compile it
with -O2?}
@ans{} You can safely clobber @sc{eax}, @sc{ecx}, and @sc{edx}, but must
save and restore all other registers at the end of your assembly
function. Failure to preserve, e.g., @sc{esi}, @sc{edi}, or @sc{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.
@node OBJ and LIB, 16-bit code, ASM and C, Converting
@comment node-name, next, previous, up
@section I want to use a @file{.obj} or @file{.lib} code with DJGPP
@cindex DOS libraries, using with GCC
@cindex DOS object files, using with GCC
@cindex .lib libraries, using with GCC
@cindex .obj object files, using with GCC
@cindex Converting DOS .obj/.lib files to GCC
@cindex .o files from EMXAOUT can't be put into a library
@pindex GCC doesn't recognize .obj object files
@pindex GCC doesn't recognize .lib libraries
@pindex OBJ2COFF converter from .obj to COFF format
@pindex OBJ2COFF, commercial use is prohibited
@pindex OBJ2BFD converter from .obj to COFF format
@quest{I have a set of useful functions in a @file{.obj} format, but no
source code. Can I use them with my DJGPP program?}
@quest{I have this @file{ACMELUXE.LIB} library of functions which I
want to use. I've extracted all the @file{.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?}
@quest{I've got a bunch of @file{.obj} files I want to use. I've ran
AR to make a GCC-style @file{.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?}
@ans{} Sorry, you probably can't. The GNU linker called by GCC doesn't
understand the format of @file{.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@footnote{
Note that mixing object files from different compilers generally doesn't
work at all, even if all the object files are in @file{.obj} format.}.
@paragraph{}
However, if you are really desperate, one conversion tool you might try
is @samp{OBJ2BFD}. It was written by @mail{Robert Hoehne,
robert.hoehne@@gmx.net} based on the @samp{EMXAOUT} utility from the
@samp{emx/gcc} package. @samp{OBJ2BFD} requires the @file{.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.
@samp{OBJ2BFD} is available @ftp{from the DJGPP sites,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2apps/o2bfd01b.zip}.
@paragraph{}
Another automated conversion tool called @samp{OBJ2COFF} was written
by the SPiRiT team, and it can be used to convert @file{.obj} object
files and @file{.lib} libraries to @samp{COFF} format, provided that the
original @file{.obj} files have been written for flat-address memory
model.
@paragraph{}
@samp{OBJ2COFF} is available via anonymous FTP transfer @ftp{from the
Oulu MSDOS repository,
x2ftp.oulu.fi/pub/msdos/programming/convert/o2cv10.arj}. If you have
any problems with it or questions about it, send them to @mail{its
author Rico, mb002@@hi.ft.hse.nl} or to @mail{George van Venrooij,
george@@il.ft.hse.nl}. Note that the authors of @samp{OBJ2COFF} have
explicitly prohibited commercial use, so you shouldn't use
@samp{OBJ2COFF} for converting commercial object files.
@paragraph{}
You can also try using @sc{lib32} librarian from Microsoft C8 to convert
object files to COFF.
@paragraph{}
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@dots{} (@xref{ASM GPF, previous
question, Converted code GP Faults!}.)
@paragraph{}
@node 16-bit code, NEAR and FAR, OBJ and LIB, Converting
@comment node-name, next, previous, up
@section I @strong{must} use my 16-bit code with DJGPP!!
@cindex DOS code, using with GCC
@cindex 16-bit code, using with DJGPP
@cindex Calling 16-bit code from DJGPP
@quest{If that's how it is, then I would have to give up using DJGPP. I
simply cannot live without these @file{.obj} files. Are you
@strong{really} sure there is nothing I can do??}
@ans{} If you need your old code @emph{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 @code{spawnXX} function
call. On the DJGPP side, you can directly call 16-bit functions from the
real-mode program using the library function called
@code{__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
@code{__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 @samp{Gas}).
@paragraph{}
@emph{Now} will you consider sticking with DJGPP? @emph{Please??@dots{}}
@node NEAR and FAR, Pseudo-registers, 16-bit code, Converting
@comment node-name, next, previous, up
@section What should I do with those ``near'' and ``far'' declarations?
@cindex far, declaration, porting to DJGPP
@cindex near, declaration, porting to DJGPP
@cindex huge, declaration, porting to DJGPP
@cindex MK_FP macro, porting to DJGPP
@cindex FP_SEG and FP_OFF, porting to DJGPP
@quest{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?}
@quest{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?}
@quest{How do I compute a segment and an offset of a protected-mode
address?}
@ans{} In DJGPP you use a flat address space with no segmentation (it
is a kind of tiny model, since @sc{cs = ds = ss}, but with a @emph{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:
@example
#define far
#define near
#define huge
#define _far
#define _near
#define _huge
@end example
Alternatively, you could add suitable @code{-D} switches to the GCC
command line, like this:
@example
gcc -Dfar= -Dnear= -Dhuge= -c myprog.c
@end example
Macros that create far pointers from the segment and offset (usually
called @code{MK_FP} or @code{_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 @code{MK_FP} in DJGPP (courtesy of @CWS{}):
@ifset html
@example
#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);
@}
@end example
@end ifset
@ifclear html
@example
#include
#include
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);
@}
@end example
@end ifclear
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
@ref{Xfer, Accessing absolute addresses, How to move data between your
program and conventional memory}, below.
@paragraph{}
Macros that extract the segment and the offset from a far pointer
(called @code{FP_SEG} and @code{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 @ref{Pointer segment, How to call
real-mode interrupt functions, How to use buffers with DOS/BIOS
services}, 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 @strong{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.
@node Pseudo-registers, , NEAR and FAR, Converting
@comment node-name, next, previous, up
@section How to convert _AX pseudo-registers?
@cindex Pseudo-register variables, porting to DJGPP
@cindex _AX variable, porting to DJGPP
@cindex _BX variable, porting to DJGPP
@cindex _CX variable, porting to DJGPP
@cindex _DX variable, porting to DJGPP
@cindex _BP variable, porting to DJGPP
@cindex _SI variable, porting to DJGPP
@cindex _DI variable, porting to DJGPP
@cindex _ES variable, porting to DJGPP
@cindex _DS variable, porting to DJGPP
@quest{Since DJGPP doesn't recognize Borland-style pseudo-register
variables like _AX, how should I port code which uses them to DJGPP?}
@ans{} These pseudo-variables are typically used in two different
contexts:
@itemize @bullet{}
@item
When calling real-mode interrupt services.
@paragraph{}
To port such code to DJGPP, use the fields of the @code{__dpmi_regs}
structure (declared on the @file{dpmi.h} header file) to set the
register values, and library function @code{__dpmi_int} to invoke the
interrupt service. For example, consider the following code snippet:
@ifset html
@example
#include <dos.h>
void _highcolor (void)
@{
_AH = 0x10;
_AL = 0x03;
_BL = 0;
geninterrupt (0x10);
@}
@end example
@end ifset
@ifclear html
@example
#include
void _highcolor (void)
@{
_AH = 0x10;
_AL = 0x03;
_BL = 0;
geninterrupt (0x10);
@}
@end example
@end ifclear
Here's one way to express this in DJGPP@footnote{
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 @code{intensevideo}, to do that, but let's
assume we have reasons not to use it.}:
@ifset html
@example
#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);
@}
@end example
@end ifset
@ifclear html
@example
#include
void _highcolor (void)
@{
__dpmi_regs r;
r.h.ah = 0x10;
r.h.al = 0x03;
r.h.bl = 0;
__dpmi_int (0x10, &r);
@}
@end example
@end ifclear
Please read @ref{int86, how to call real-mode interrupt functions,
Calling real-mode interrupts}, elsewhere in this document, for further
details on how call real-mode services from DJGPP programs.
@paragraph{}
@item
Immediately before or after an inline assembly code.
@paragraph{}
GCC features extensive inline assembly facilities which allow you to
assign values to, or read values from registers from the inline assembly
code. See @ref{Inline Asm, description of inline assembly, Inline
Assembly code with GCC}, for further info.
@end itemize
@node Low-level, Legalese, Converting, Top
@comment node-name, next, previous, up
@chapter Low-level DOS/BIOS and Hardware-oriented Programming
@cindex Low-level programming issues
@cindex Systems programming issues
@cindex Hardware-oriented programming
This chapter sheds some light on a few aspects of writing DJGPP programs
which interact with hardware or use interrupts.
@menu
* int86:: It doesn't always work.
* Pointer segment:: Some interrupts require it, but how do you get it?
* Zero SP:: If you don't, your program crashes.
* Xfer:: Moving data to and from conventional memory.
* Move structs:: How to move structs from conventional memory.
* Fat DS:: Fast direct access to memory-mapped devices.
* Above 1MB:: Interact with memory-mapped devices above 1MB.
* RMCB:: How to let DOS/BIOS call your code.
* Hardware interrupts:: How to hook HW interrupts from DJGPP.
* _go32 vs __dpmi:: Which functions should you use?
* HW Int pitfalls:: Does your machine wedge? Here are some reasons.
* Ports:: Reading and writing I/O ports in DJGPP.
* Inline Asm:: How to write inline assembly with GCC.
* DMA:: How to use DMA from DJGPP programs.
@end menu
@node int86, Pointer segment, Low-level, Low-level
@comment node-name, next, previous, up
@section Got ``Unsupported INT 0xNN'' calling @code{int86}
@cindex Unsupported INT message
@cindex Unsupported DOS request message
@cindex int86 crashes program
@cindex intdos crashes program
@cindex Program crashes in int86/intdos
@cindex DOS service calls
@cindex BIOS service calls
@cindex __dpmi_int, calling DOS/BIOS services
@quest{Why does my program crash with ``Unsupported DOS request 0xNN''
or ``Unsupported INT 0xNN'' when I call @code{int86} or @code{intdos}
functions to invoke a software interrupt?}
@ans{} Calling real-mode DOS or BIOS services from protected-mode programs
requires a switch to real mode, so the @code{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 @code{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
@code{int86} supports many of these services, it doesn't support all of
them. The supported functions are listed in the library reference.
@extrefx{int86, int86, libc.inf, libc.a reference,
www.delorie.com/djgpp/doc/libc-2.01/libc_411.html#SEC411}. For those it
doesn't support, you will have to call the @code{__dpmi_int} library
function instead. It is also documented in the library reference,
@extref{__dpmi_int, __dpmi_int, libc.inf, libc.a reference,
www.delorie.com/djgpp/doc/libc-2.01/libc_208.html#SEC208}.
@code{__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 (@pxref{Pointer segment, how to use buffers with DOS/BIOS
services, How to move data between your program and conventional
memory}).
@paragraph{}
@cindex int86/intdos, garbled results in registers
@cindex int86/intdos, registers' width
Note that calling @code{int86} and @code{intdos} can sometimes cause
trouble due to size (16 bits as opposed to 32 bits) of the members in
the @code{union REGS} structure. Do @emph{not} assume that
e.g. @code{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; @extref{int86, description of the int86 function,
libc.inf, libc.a reference,
www.delorie.com/djgpp/doc/libc-2.01/libc_411.html#SEC411}.
@cindex Mouse interface, problems with int86
@cindex int86, problems with mouse interface
In particular, programs which interface with the mouse via calls to the
@code{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).
@node Pointer segment, Zero SP, int86, Low-level
@comment node-name, next, previous, up
@section How to use buffers with DOS/BIOS services
@cindex DOS service calls which need buffers
@cindex BIOS service calls which need buffers
@cindex int86x/intdosx, how to pass a buffer
@cindex __dpmi_int, how to pass buffers
@cindex Transfer buffer, using to call DOS/BIOS
@cindex __tb, an alias for the address of transfer buffer
@quest{I want to call a DOS/BIOS function which requires a pointer to a
buffer in, e.g. @sc{es:di} (or any other) register pair. How do I get
the segment to put into the @sc{es} register?}
@quest{I have some real-mode code that calls the @code{segread}
function. How can I make it work with DJGPP?}
@ans{} If you use @code{int86x} or @code{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 (@code{regs.x.di}), forget
about the segment, and call @code{int86} or @code{intdos} instead of
@code{int86x} and @code{intdosx}. The DOS/BIOS functions supported by
@code{int86} and @code{intdos} are processed specially by the library,
which will take care of the rest. Note that calling @code{int86x} and
@code{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 @code{__dpmi_int},
see below.
@paragraph{}
If you call @code{__dpmi_int}, then you must put into that register pair
an address of some buffer in @emph{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
@code{_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:
@smallexample
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;
@end smallexample
For your convenience, the header file @file{go32.h} defines a macro
@code{__tb} which is an alias for
@code{_go32_info_block.linear_address_of_transfer_buffer.}
@paragraph{}
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 @code{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 @code{dosmemget}.
@ifset html
@example
#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, ®s); /* 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;
@}
@}
@end example
@end ifset
@ifclear html
@example
#include
#include
#include
#include
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, ®s); /* 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;
@}
@}
@end example
@end ifclear
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
@code{__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 @code{exit.}
@paragraph{}
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 @samp{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).
@paragraph{}
@cindex segread function, how to port to DJGPP
The function @code{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
@sc{cs}, @sc{ds}, @sc{ss}, and @sc{es} registers into a @code{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 @code{_my_cs}, @code{_my_ds}, and @code{_my_ss} for that
purpose (@sc{es} and @sc{ds} always hold the same selector in code
produced by GCC from a C or C@t{++} 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
@code{__dpmi_int}, as described above.
@node Zero SP, Xfer, Pointer segment, Low-level
@comment node-name, next, previous, up
@section How to call software interrupt functions
@cindex Software interrupts, need zero SS, SP and FLAGS
@cindex __dpmi_simulate_real_mode_interrupt, need zero SS, SP and FLAGS
@cindex __dpmi_int, use to invoke software interrupts
@quest{My program crashes/doesn't do what it should when I call
@code{__dpmi_simulate_real_mode_interrupt.}}
@ans{} You should zero out some of the members of the @code{__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
@code{.x.ss}, @code{.x.sp}, and @code{.x.flags}. When @code{.x.ss} and
@code{.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@footnote{
The DPMI spec indicates that you should @emph{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.}. In these
cases you should point @code{.x.ss} and @code{.x.sp} to a larger buffer
which is in conventional memory (possibly part of the transfer buffer).
@paragraph{}
If @sc{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 @sc{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!).
@paragraph{}
If you don't have any reason to set @sc{ss:sp} to a user-defined
stack, it's easier to call the @code{__dpmi_int} library function, which
zeroes out the stack pointer and the @sc{flags} fields for you (and
also doesn't force you to type long function names!).
@node Xfer, Move structs, Zero SP, Low-level
@comment node-name, next, previous, up
@section How to move data between your program and conventional memory
@cindex Transfer buffer, moving data
@cindex Accessing absolute addresses in conventional memory
@cindex Accessing absolute addresses with dedicated selector
@cindex Moving data to and from transfer buffer
@cindex Moving data to and from conventional memory
@cindex Conventional memory, moving data to/from
@cindex Memory-mapped devices, moving data to/from
@cindex Memory-mapped devices, accessing with dedicated selector
@cindex Peripherals, moving data to/from
@cindex Peek/poke absolute address
@cindex nearptr method of direct memory access
@cindex _dos_ds, a selector to access conventional memory
@quest{How can I move data between my program and the transfer buffer?}
@quest{How do I access my peripheral card which is memory-mapped to an
address between 640K and 1M?}
@quest{How can I read or change a value of one of the variables in the
BIOS data area?}
@quest{How can I peek at an address whose far pointer I get from an
@w{INT 21h} call?}
@ans{} 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 @sc{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:
@itemize @bullet{}
@item
Use the selector that DJGPP creates for itself to access conventional
memory. DJGPP makes this selector available to you via the
@code{_dos_ds} macro (defined on the @file{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@footnote{
DJGPP v2.01 makes the limit of @code{_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.}. The advantage of @code{_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.
@paragraph{}
@item
Create your own selector that spans only the region of memory that you
want to access, and use that selector instead of @code{_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 @code{0xB800:0000}, courtesy
of @mail{Bill Currie, bill@@tanihwa.tssc.co.nz}@footnote{
If you want to decipher the 8-byte structure that is passed to
@code{__dpmi_set_descriptor} in this example, read the documentation of
the @code{__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 @sc{cs}
and @sc{ds} registers.}:
@smallexample
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;
@}
@end smallexample
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.
@paragraph{}
@item
Use the DPMI service which creates a selector to access a specific
real-mode segment address. The DJGPP library has a function
@code{__dpmi_segment_to_descriptor} which is a wrapper around that DPMI
service. It is easier to use than the @code{__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 @code{0xA000:0000}:
@example
short video = __dpmi_segment_to_descriptor(0xa000);
@end example
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 @code{__dpmi_set_segment_base_address} library function
instead of using @code{__dpmi_segment_to_descriptor} to allocate
separate descriptor for each address.
@paragraph{}
@end itemize
Once you have a selector, you can use one of three methods to access
your absolute addresses using that selector:
@itemize @bullet{}
@item
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 @code{}
header file. You should convert any real-mode far pointer
segment:offset pair into a @dfn{linear address} (i.e., segment*16 +
offset), and use @code{_dos_ds} or any other selector which allows
access to conventional memory, like this:
@smallexample
unsigned char value = _farpeekb(_dos_ds, segment * 16 + offset);
@end smallexample
For access to memory-mapped devices for which you have allocated a
dedicated descriptor, use the selector of that descriptor instead of
@code{_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:
@example
long lword = 3;
_farpokel (selector, 9, lword);
@end example
Use @code{_farpeekw} to peek at 16-bit shorts and @code{_farpeekl} to
peek at 32-bit longs. If you need to access several (non-contiguous)
values in a loop, use the corresponding @code{_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).
@paragraph{}
There is a corresponding set of @code{_farpokeX} and @code{_farnspokeX}
functions to poke (change the values of) such memory locations.
@paragraph{}
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.
@paragraph{}
@item
If you need to access more than 4 contiguous bytes, use @code{dosmemget}
and @code{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 @code{_dos_ds} internally).
@paragraph{}
Note that some memory-mapped peripheral devices might require 16-bit word
accesses to work properly, so if @code{dosmemXXX} yields garbled
results, try @code{dosmemXXXw} or set up a loop which calls ``farptr''
functions.
@paragraph{}
@item
For moving buffers to selectors other than @code{_dos_ds} (e.g., created
by one of the methods explained above), use the @code{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 @code{_my_ds()} function (note that it's a
@strong{function}, not a variable!) to get the selector of any variable
in your program, and use the address of the variable (cast to an
@code{int}) as its ``offset'' or linear address. @code{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 @code{movedatab} and @code{movedataw} are provided for moving
by bytes and by 16-bit words, respectively.
@paragraph{}
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
@code{movedata} to move a buffer to the graphics screen:
@example
short video = __dpmi_segment_to_descriptor(0xa000);
movedata(_my_ds(), buffer, video, 0, 320*200);
@end example
@item
For the fastest access to memory outside your usual address space, you
might consider using the ``nearptr'' functions declared on the
@file{sys/nearptr.h} header file; see the library reference for more
details. Also see @ref{Fat DS, description of how to get the fastest
direct access to peripheral devices, Fast access to absolute addresses},
below.
@end itemize
@node Move structs, Fat DS, Xfer, Low-level
@comment node-name, next, previous, up
@section How to move structs returned by real-mode services?
@cindex Struct declaration, for real-mode services
@cindex VBE services, struct declaration
@quest{My program uses the contents of a structure returned by a VBE
function, but some of the struct members are garbled!}
@ans{} 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.
@paragraph{}
Here are some gotchas in this context:
@itemize @bullet{}
@item
The structure should be declared with @code{__attribute__((packed))}, to
prevent GCC from inserting gaps between some members to make them
properly aligned for faster access (@pxref{Struct size, how gcc aligns
structs, What should sizeof (struct xyzzy) return?}). C programs can
declare the entire struct with the packed attribute, but C@t{++}
programs will need to declare each member with it, see @ref{Struct size,
__attribute__((packed)), Packing struct members}.
@paragraph{}
@item
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.
@paragraph{}
@item
To use pointers which are members of the structure, you will have to
employ some of the methods described in @ref{Xfer, section about using
the transfer buffer, How to move data between your program and
conventional memory}. For example, to copy data whose real-mode address
is returned in a struct, use @code{dosmemget} or one of the
@code{_farpeekX} family of functions in conjunction with the
@code{_dos_ds} selector, and don't forget to compute the linear address
as @code{segment * 16 + offset}.
@paragraph{}
@item
@cindex Real-mode functions, how to call
@cindex Calling real-mode functions
If the pointer is to a function, you will need to use the library
function @code{__dpmi_simulate_real_mode_procedure_retf} to call it
(don't forget to zero out the @code{.x.ss} and @code{.x.sp} members of
the @code{__dpmi_regs} structure!).
@paragraph{}
@item
Many real-mode compilers use 16-bit @code{int}s, whereas in DJGPP, an
@code{int} is 32-bit wide. You need to change the declaration of all
struct members from @code{int} to @code{short}, and from @code{unsigned}
to @code{unsigned short}.
@end itemize
For example, the following real-mode structure declaration:
@example
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 */
@};
@end example
@noindent
should be converted to this in a DJGPP program:
@example
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));
@};
@end example
@node Fat DS, Above 1MB, Move structs, Low-level
@comment node-name, next, previous, up
@section Fast access to absolute addresses
@cindex Peripheral devices, fast access
@cindex Memory-mapped devices, fast access
@cindex sbrk, effect on ``Fat DS''
@cindex Nearptr functions
@cindex malloc, effect on ``Fat DS''
@cindex calloc, effect on ``Fat DS''
@cindex realloc, effect on ``Fat DS''
@pindex CWSDPMI allows ``Fat DS''
@pindex QDPMI allows ``Fat DS''
@pindex Windows 3.X allows ``Fat DS''
@pindex Windows 9X allows ``Fat DS''
@pindex OS/2 Warp allows ``Fat DS''
@pindex Linux doesn't allow ``Fat DS''
@pindex DOSEMU doesn't allow ``Fat DS''
@pindex Windows/NT doesn't allow ``Fat DS''
@quest{The ``farptr'' functions are too slow for my application which
@strong{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! @t{:-(}}
@ans{} The following so-called @b{Fat DS}, or ``nearptr'' method was
suggested by @mail{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 @Steve{}
has put it when he read the description of this trick:
@quotation
@strong{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.
@end quotation
@paragraph{}
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.
@paragraph{}
Having said that, here is the trick: you change the limit of the segment
descriptor stored in @sc{ds} to @code{0xffffffff} (i.e., -1), using
library function @code{__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
@code{__djgpp_conventional_base} to the target address.
@code{__djgpp_conventional_base} is the negated base address of the
@sc{ds} selector that you program is using to access its data. By
adding the value of @code{__djgpp_conventional_base}, you effectively
@emph{subtract} the @sc{ds} base address, which makes the result
zero-based, exactly what you need to access absolute addresses.
@paragraph{}
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 @code{__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 @code{malloc} or any
other library function which calls @code{sbrk} might sometimes change
the base address of the @sc{ds} selector and break this method unless
the base address is recomputed after @code{sbrk} call. (The ``nearptr''
functions support this recomputation by providing you with the
@code{__djgpp_conventional_base} variable, but it is @emph{your}
responsibility to recompute the pointers using it.) The same change can
happen when you call @code{system}, and as a result of some other events
external to the executing code thread, like multitasking or debugger
execution.
@paragraph{}
You should also know that the @code{__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 @strong{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.
@paragraph{}
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.
@paragraph{}
Confused about how exactly should you go about using this technique in
your program? Look at the docs of the ``nearptr'' functions,
@extref{__djgpp_nearptr_enable, __djgpp_nearptr_enable, libc.inf, libc.a
reference, www.delorie.com/djgpp/doc/libc-2.01/libc_122.html#SEC122}.
@paragraph{}
Another possibility is to use the DPMI function @code{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
@strong{not} supported by most DPMI 0.9 hosts (CWSDPMI does support it).
There is a helper function @code{__djgpp_map_physical_memory} in the
DJGPP C library that you can use to call these services.
@node Above 1MB, RMCB, Fat DS, Low-level
@comment node-name, next, previous, up
@section Accessing absolute address above 1MB
@cindex Peripheral devices above 1MB
@cindex Memory-mapped devices above 1MB
@cindex Accessing absolute addresses above 1MB
@quest{How can I access memory-mapped peripheral devices (or any other
absolute address) above 1 MByte mark?}
@ans{} 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:
@itemize @minus{}
@item
map selector to physical address (Int 31h/AX=0800h);
@item
allocate an LDT descriptor (Int 31h/AX=0);
@item
set segment base address (Int 31h/AX=7);
@item
set segment limit (Int 31h/AX=8).
@end itemize
All of these DPMI calls have @code{__dpmi__XXX} wrappers in the DJGPP
library. Here's a somewhat schematic example:
@smallexample
@ifset html
#include <dpmi.h>
@end ifset
@ifclear html
#include
@end ifclear
.
.
__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);
@end smallexample
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 @file{sys/farptr.h} header file
to access that device. @xref{Xfer, accessing memory-mapped devices, How
to move data between your program and conventional memory}, for more
details about accessing memory-mapped devices given their linear
address.
@node RMCB, Hardware interrupts, Above 1MB, Low-level
@comment node-name, next, previous, up
@section How to make DOS/BIOS call your function
@cindex Real-mode call-back
@cindex Real-mode services, calling DJGPP functions
@cindex Mouse handler, how to install with DJGPP
@quest{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 @sc{es:dx} register pair.}
@ans{} 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 @code{_go32_dpmi_allocate_real_mode_callback_retf} or the
@code{_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 @code{__dpmi_int.}
Here's a code fragment that shows how to do this@footnote{
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 @code{_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.}:
@ifset html
@smallexample
#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;
@}
@end smallexample
@end ifset
@ifclear html
@smallexample
#include
#include
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;
@}
@end smallexample
@end ifclear
The handler (@code{func} in the above example) will be called with a
pointer to a @code{__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.
@node Hardware interrupts, _go32 vs __dpmi, RMCB, Low-level
@comment node-name, next, previous, up
@section How to hook hardware interrupts
@cindex Hardware interrupts, hooking
@cindex Interrupts handlers in DJGPP
@cindex Interrupt reflection
@cindex __dpmi_get_real_mode_interrupt_vector
@cindex __dpmi_get_protected_mode_interrupt_vector
@cindex _go32_dpmi_allocate_iret_wrapper
@cindex _go32_dpmi_chain_protected_mode_interrupt_vector
@cindex Real-mode interrupt vector
@cindex Protected-mode interrupt vector
@cindex Chaining interrupt
@cindex Interrupt chaining
@cindex Locking memory for hardware interrupt handlers
@cindex Memory locking for hardware interrupt handlers
@cindex Virtual memory, disabling with startup flags
@cindex Paging, how to disable
@pindex CWSDPR0, use for testing HW interrupt handlers
@quest{How do I register my DJGPP function as a hardware interrupt handler?}
@ans{} 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.
@paragraph{}
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
@emph{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.
@paragraph{}
To install a protected-mode interrupt handler, you do this:
@paragraph{}
@itemize @bullet{}
@item
In general, your handler should be written in assembly to be
bullet-proof. You should lock@footnote{
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.} 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 (@pxref{DPMI
Spec, DOS Protected Mode Interface Specification, Where to find the DPMI
specification?}). To install an assembly handler, you should do this:
@paragraph{}
@itemize @minus{}
@item
Call @code{__dpmi_get_protected_mode_interrupt_vector} and save the
structure it returns (to restore the previous handler address before your
program exits).
@item
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
@code{__dpmi_lock_linear_region}. Failure to lock memory accessed
during the interrupt handling will cause your program to crash.
Alternatively, you could set the @code{_CRT0_FLAG_LOCK_MEMORY} bit in
the @code{_crt0_startup_flags} variable, or disable virtual memory by
using CWSDPR0.
@item
Finally, call @code{__dpmi_set_protected_mode_interrupt_vector} and pass
it a pointer to a @code{__dpmi_paddr} structure filled with the value
returned by @code{_my_cs()} in the @code{selector} field and the address
of your function in the @code{offset32} field.
@end itemize
@paragraph{}
@item
If your handler function is written in C, you should generally call the
@code{_go32_dpmi_XXX} functions instead of the bare-bones API wrappers
whose names start with @code{__dpmi_.} Specifically:
@paragraph{}
@itemize @minus{}
@item
Call @code{_go32_dpmi_get_protected_mode_interrupt_vector.} This
function puts the selector and offset of the specified interrupt vector
into the @code{pm_selector} and @code{pm_offset} fields of the structure
pointed to by its second argument. This data should be saved and later
passed to @code{_go32_dpmi_set_protected_mode_interrupt_vector} to
restore the vector on exit.
@item
Call @code{_go32_dpmi_allocate_iret_wrapper,} passing it the address of
your function in the @code{pm_offset} field and the value returned by
@code{_my_cs()} in the @code{pm_selector} field. The @code{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 @code{interrupt} or @code{_interrupt} keyword in
some DOS-based compilers.
@item
If you want your handler to chain to the previous handler, call
@code{_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 @code{pm_offset} field and the value of
@code{_my_cs} into the @code{pm_selector} field of the
@code{_go32_dpmi_seginfo} structure and pass a pointer to it to this
function.
@item
You then call @code{_go32_dpmi_set_protected_mode_interrupt_vector} with
the address of the @code{_go32_dpmi_seginfo} structure you got from either
@code{_go32_dpmi_allocate_iret_wrapper} or
@code{_go32_dpmi_chain_protected_mode_interrupt_vector.}
@end itemize
@paragraph{}
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
@code{_CRT0_FLAG_LOCK_MEMORY} bit in the @code{_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.
@paragraph{}
@cindex Locking memory, silent failure
@cindex Memory locking, silent failure
@cindex _CRT0_FLAG_LOCK_MEMORY, silent failure
Note that @code{_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.
@end itemize
@paragraph{}
To install a real-mode interrupt handler, you do this:
@paragraph{}
@itemize @bullet{}
@item
Call @code{__dpmi_get_real_mode_interrupt_vector} and save the structure
it returns (to restore the previous handler address before your program
exits).
@item
Allocate some conventional memory with @code{__dpmi_allocate_dos_memory}
and put the code of your handler there with the @code{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?)
@item
Put the address which @code{__dpmi_allocate_dos_memory} returned into a
@code{__dpmi_raddr} structure (the lower 4 bits into @code{offset16}
field, the rest into @code{segment} field), then call
@code{__dpmi_set_real_mode_interrupt_vector.}
@end itemize
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.
@paragraph{}
@cindex Interrupts 1Ch, 23h, 24h
The DPMI spec says that 3 @emph{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.
@paragraph{}
For examples of installing and using hardware interrupt handlers, see
the sources of the Allegro library, the sample code written by
@mail{Bill Currie, bill_currie@@MAIL.TAIT.CO.NZ}, the Sound Blaster
interrupt-driven functions, the @samp{mkkbd} package, and the
@samp{libhw} library, described under @ref{Samples, sample DJGPP
packages, Where to find sample DJGPP code or a package ported to DJGPP}.
@mail{Alaric B. Williams, alaric@@abwillms.demon.co.uk} has written a
@www{tutorial on interrupt handling,
www.abwillms.demon.co.uk/prog/djints.txt}.
@paragraph{}
The file @file{src/libc/crt0/crt0.S} in the DJGPP library sources,
@file{djlsrNNN.zip}, is one example of the subtleties involved with
installing a real-mode interrupt handler.
@node _go32 vs __dpmi, HW Int pitfalls, Hardware interrupts, Low-level
@comment node-name, next, previous, up
@section Should I use _go32_XXX or __dpmi_YYY functions?
@cindex _go32_XXX vs __dpmi_YYY, which one to use
@cindex __dpmi_YYY vs _go32_XXX, which one to use
@quest{In v1.x I was used to the @code{_go32_@dots{}} functions, but
now comes v2 which also has @code{__dpmi_@dots{}} functions. Are there
any differences between these two varieties?}
@quest{Do I need to convert my old v1.x code to use the new
@code{__dpmi_@dots{}} functions?}
@ans{} 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 @code{__dpmi_@dots{}} functions are just
bare-bones wrappers of the DPMI API calls (@pxref{DPMI Spec, DPMI
Specification, Where to find the DPMI specification}), generally
unsuitable for use with handlers written in C, whereas the old
@code{_go32_@dots{}} 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 @sc{ds}, @sc{ss}, and @sc{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.
@paragraph{}
The problem with the @code{_go32_@dots{}} 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
@code{#define}d to the new names where the functionality is identical.
@paragraph{}
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 @code{__dpmi_@dots{}} functions (@pxref{Hardware interrupts, How to
install a hardware interrupt handler, How to hook hardware interrupts}).
@node HW Int pitfalls, Ports, _go32 vs __dpmi, Low-level
@comment node-name, next, previous, up
@section Hardware interrupt hooking has its subtleties
@cindex Hardware interrupts, subtleties
@cindex Hardware interrupt handler crashes
@cindex Interrupt frequency, maximum
@cindex Maximum interrupt frequency
@cindex Interrupt handlers, locking memory
@cindex Locking memory for interrupt handlers
@cindex Unix-like sbrk algorithm considered harmful for HW interrupts
@cindex Keystrokes don't get to keyboard handler
@cindex Overhead, interrupt reflection to protected mode
@cindex Interrupt reflection overhead
@cindex _crt0_startup_flags, setting to lock memory
@cindex _crt0_startup_flags, Unix sbrk is incompatible with HW interrupts
@cindex sbrk, Unix-like algorithm is incompatible with HW interrupts
@pindex EMM386, effect on max interrupt frequency
@pindex CWSDPR0 reduces interrupt reflection overhead
@pindex PMODE/DJ reduces interrupt reflection overhead
@quest{I did all the above, but my program occasionally still hangs@dots{}}
@quest{From time to time my program crashes with a message ``Page Fault
in RMCB''. What's that?}
@ans{} 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 @strong{if you play by the rules}.
Unfortunately, the rules are a bit tricky.
@paragraph{}
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
@code{__dpmi_lock_linear_region} library function. This also means in
practice that you should write your handler in assembly, as described in
@ref{Hardware interrupts, how to set an interrupt handler, How to hook
hardware interrupts}, above. You can disable virtual memory, or put
@code{_CRT0_FLAG_LOCK_MEMORY} into @code{_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).
@paragraph{}
@cindex Mouse callback crashes with Page Fault in RMCB
@cindex Page Fault in RMCB message
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@footnote{
Actually, it is possible to avoid reentrancy problems in
interrupt-driven programs: programs known as TSRs (@dfn{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.}. 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.
@paragraph{}
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.
@paragraph{}
If all that still doesn't help, install a real-mode handler.
@paragraph{}
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.
@paragraph{}
Still another possibility is that you use a non-default @code{sbrk}
algorithm in your program. Check if the header file @file{crt0.h} is
included anywhere in the program, and if so, if the
@code{_CRT0_FLAG_UNIX_SBRK} bit in the @code{_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.
@paragraph{}
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
@kbd{Ctrl-Alt-Del} combination to your keyboard interrupt handler, but
will rather act on it itself; QDPMI sometimes processes @kbd{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
@file{.PIF} file).
@paragraph{}
If the above still doesn't explain your problem, then post your code on
the @mail{DJGPP mailing list, djgpp@@delorie.com} or
@news{comp.os.msdos.djgpp}, tell there how it fails and somebody will
usually have a solution or a work-around for you.
@node Ports, Inline Asm, HW Int pitfalls, Low-level
@comment node-name, next, previous, up
@section How to read and write ports
@cindex Peripheral devices, reading/writing ports
@cindex Port reading/writing
@cindex inp function
@cindex outp function
@quest{I need to read from and write to PC ports, and I'm accustomed to
using the @code{inp} and @code{outp} functions. But I hear they aren't
available in DJGPP?}
@ans{} They are in v2.x. Just
@ifset html
@code{@w{#include <pc.h>}}
@end ifset
@ifclear html
@code{@w{#include }}
@end ifclear
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 @w{dword-long} access (e.g., @code{inportl} for reading
a 32-bit dword), as well as functions to read/write sequences of bytes
and words, like @code{inportsb} and @code{outportsw}; these are
DJGPP-specific.
@node Inline Asm, DMA, Ports, Low-level
@comment node-name, next, previous, up
@section Inline Assembly code with GCC
@cindex Inline assembly, how to write
@cindex Accessing C variables from inline assembly
@pindex GCC, inline assembly facilities
@quest{I am used to writing inline assembly with Borland C, but can't
figure out the way to do it with GCC@dots{}}
@quest{How can I reference C variables from my inline assembly code?}
@ans{} 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:
@example
info gcc "C Extensions" "Extended Asm"
@end example
@noindent
(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
@file{v2gnu/txi@value{txi-version}b.zip} from the DJGPP distribution and
install it.
@paragraph{}
If you read this FAQ via WWW, you can also @www{read about the GCC
inline assembly extensions with your Web browser,
www.delorie.com/gnu/docs/gcc-2.7.2.2/gcc_86.html#SEC89}.
@paragraph{}
@mail{Brennan Underwood, brennan@@rt66.com} has written @www{a tutorial
on using inline assembly, brennan.home.ml.org/djgpp/djgpp-asm.html},
which is another valuable resource on this issue.
@node DMA, , Inline Asm, Low-level
@comment node-name, next, previous, up
@section Using DMA with DJGPP
@cindex DMA, using from DJGPP programs
@cindex VDS, not supported by CWSDPMI (yet)
@quest{How do I use DMA with DJGPP programs?}
@quest{I want to use DMA, but I don't know how to get the physical
address of the buffer I allocate for that purpose.}
@ans{} 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 @code{__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.
@paragraph{}
You have two alternatives to get the physical address of your buffer:
@itemize @bullet{}
@item
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 @code{__dpmi_allocate_dos_memory}.
@paragraph{}
This method has a disadvantage of using conventional memory which is at
a premium, and is therefore generally ill-suited for large DMA buffers.
@paragraph{}
@item
Use @dfn{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 @code{EMM386} or @code{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@footnote{
CWSDPMI has an experimental VDS support in its sources, but the
distributed binary was compiled without it. Contact @CWS{} if you want
to try to enable VDS support in CWSDPMI.} is used as the DPMI server,
allocating memory by raw XMS calls or via HIMEM.
@end itemize
@node Legalese, Help, Low-level, Top
@comment node-name, next, previous, up
@chapter Legal Aspects
@cindex Legal aspects of DJGPP programming
@cindex Copyright issues
This chapter answers some questions about various legal aspects of
writing programs with DJGPP.
@menu
* Application distribution:: Legal aspects of programs written with DJGPP.
* DJGPP redistribution:: Legal aspects of redistributing DJGPP itself.
@end menu
@node Application distribution, DJGPP redistribution, Legalese, Legalese
@comment node-name, next, previous, up
@section Legal (un)restrictions on DJGPP applications
@cindex GPL, effect on DJGPP
@cindex LGPL, effect on DJGPP
@cindex GNU Copyleft, effect on DJGPP
@cindex Copyleft, effect on DJGPP
@cindex Legal restrictions on DJGPP apps
@cindex DJGPP applications, legal restrictions
@cindex Commercial programs, writing with DJGPP
@cindex C@t{++} class libraries, legal restrictions
@cindex libgpp.a, legal restrictions
@cindex libiostream.a, legal restrictions
@pindex Flex doesn't imply GPL/LGPL
@pindex Bison doesn't imply GPL/LGPL
@quest{Can you explain in plain English the legal restrictions of
distributing programs compiled with DJGPP?}
@quest{Can I write commercial programs with DJGPP?}
@ans{} 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.
@paragraph{}
Using the GNU C/C@t{++} compiler doesn't make your programs subject to
@emph{any} restrictions. The C library which comes with DJGPP is
@emph{free} (unless you change the library sources, see below), which
means you are free to use the stock @file{libc.a} in any way you like
(but please try to comply with @ref{DJGPP redistribution, basic rules of
courtesy, Legal restrictions of DJGPP utilities and libraries}.)
@paragraph{}
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 @code{malloc}, which is by default
linked into every DJGPP program (the startup code calls it), the others
are time-related functions such as @code{time}, @code{ctime}, and
@code{asctime}, and also @code{qsort} and @code{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:
@display
This product includes software developed by the University of
California, Berkeley and its contributors.
@end display
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.
@paragraph{}
The basic C@t{++} @samp{iostream} class library (@file{libiostr.a}) and the
Standard Template Library (@file{libstdcxx.a}) which come with DJGPP
allow you to use them binary-wise (i.e., without changing library
sources) in your C@t{++} programs @emph{without restrictions}, unless you
compile your programs with a compiler other than Gcc (which won't happen
if you work with DJGPP). So C@t{++} programs linked with
@samp{-lstdcxx} and/or @samp{-liostream} switches are also free from any
restrictions.
@paragraph{}
Only the library of additional GNU C@t{++} classes (@file{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@t{++} library. However, this library is
deprecated and chances are most C@t{++} programs won't use it. (If you
intend to distribute commercial programs linked with the @file{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.)
@paragraph{}
Two GNU packages, @samp{Flex} and @samp{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 @samp{Flex} and parsers
produced by @samp{Bison} do @strong{not} imply GPL/LGPL.
@paragraph{}
If you @strong{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 @samp{getopt}
or @samp{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 @samp{regex} and
@samp{getopt} from the DJGPP C library (which are not as powerful, but
are free from any restrictions).
@paragraph{}
You may ship any of the utilities developed specifically for DJGPP
(e.g., the floating-point emulator @file{emu387.dxe} or the DPMI host
@file{cwsdpmi.exe}) and the C library, @emph{as distributed by DJ
Delorie}, with your program with no other requirement besides telling
your customers how to get DJGPP for themselves.
@paragraph{}
If you do change the sources of either the C library or the utilities
distributed with the @samp{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 @file{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 @file{libc.a} (even if no official
DJGPP version was released with your patches yet).
@paragraph{}
For the precise legal terms of DJGPP distribution, see the file
@www{@file{copying.dj} via the Web,
www.delorie.com/djgpp/dl/ofc/simtel/v2/copying.dj} (latest versions of
the @file{djdevNNN.zip} package might also include it).
@paragraph{}
Note that the above says nothing about the legal aspects of contributed
packages, like @samp{GRX} and others; you will need to read their docs
to find out.
@node DJGPP redistribution, , Application distribution, Legalese
@comment node-name, next, previous, up
@section Legal restrictions of DJGPP utilities and libraries
@cindex Legal restrictions, DJGPP utilities
@cindex DJGPP utilities, legal restrictions
@cindex C library, legal restrictions
@pindex CWSDPMI, legal restrictions
@quest{Can I redistribute djgpp, and if so, how?}
@quest{I run a business that sells shareware for distribution costs. Can
I include djgpp on my CD-ROM?}
@quest{I want to include djgpp in a product that happens to need a
compiler provided with it. Can I do this?}
@quest{Is DJGPP public domain software?}
@quest{Is DJGPP shareware?}
@ans{} DJGPP is @strong{not} public domain, neither is it shareware (you
@emph{don't} have to pay a license fee to use DJGPP). Parts of DJGPP (the
compiler and some of the development tools) @emph{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.
@paragraph{}
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.
@paragraph{}
@emph{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:
@itemize @bullet{}
@item
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{}.
@item
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.
@item
You @strong{must} call it @emph{DJGPP} and nothing else.
@item
You may @strong{not} take credit for it, and you must @strong{not} remove
any notices in DJGPP that give credit to those who worked on it.
@item
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. @w{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.
@end itemize
@paragraph{}
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.
@paragraph{}
Note that the above are @strong{not} legal restrictions (the latter are
described in the file @file{copying.dj} mentioned in the previous
section), they are @emph{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.
@paragraph{}
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.
@node Help, New versions, Legalese, Top
@comment node-name, next, previous, up
@chapter Getting Help
@cindex Getting more help
@cindex More help, how to get
This chapter tells you how to get answers to questions you didn't find
in this FAQ, by asking them on DJGPP-related forums.
@menu
* DJGPP is not GNU:: Do @strong{not} post to GNU News groups.
* Mailing list:: How to post to DJGPP mailing list.
* Subscribing:: You can see every posted article.
* Unsubscribing:: When it's too much to read@dots{}
@end menu
@node DJGPP is not GNU, Mailing list, Help, Help
@comment node-name, next, previous, up
@section Don't post DJGPP-specific problems to GNU News groups
@cindex GNU News groups, don't post DJGPP problems
@cindex Posting problems, not to GNU News groups
@quest{I post my problem to @news{gnu.gcc.help}, but don't get any
answers@dots{}}
@ans{} 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
@news{comp.os.msdos.djgpp} or to the @mail{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.
@node Mailing list, Subscribing, DJGPP is not GNU, Help
@comment node-name, next, previous, up
@section How to post to the mailing list
@cindex DJGPP mailing list, how to post
@cindex Posting to DJGPP mailing list
@quest{How do I post to the DJGPP mailing list?}
@ans{} Send mail to the @mail{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,
@url{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 @b{;-)}; 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.
@paragraph{}
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 @www{searching,
www.delorie.com/djgpp/mail-archives/}.
@paragraph{}
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.
@node Subscribing, Unsubscribing, Mailing list, Help
@comment node-name, next, previous, up
@section How to become a subscriber to the mailing list
@cindex DJGPP mailing list, how to subscribe
@cindex Subscription to DJGPP mailing list
@cindex Announcements, mailing list
@cindex DJGPP-ANNOUNCE mailing list
@cindex DJGPP mailing list, in digest form
@cindex Weekly digest, problems in receiving
@quest{How do I subscribe to the DJGPP mailing list?}
@ans{} Send mail to the @mail{list server, listserv@@delorie.com} (NOT
to djgpp@@!!), leave the subject line empty and in the body write:
@quotation
subscribe djgpp
@end quotation
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 @samp{djgpp-announce} by sending message to the @mail{list
server, listserv@@delorie.com} which says so:
@quotation
subscribe djgpp-announce
@end quotation
@noindent
(Note: no email address when subscribing to the @samp{djgpp-announce}
list!)
The announcements which go to @samp{djgpp-announce} get reflected to
@samp{djgpp}, so you don't need to subscribe to both these lists.
@paragraph{}
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:
@quotation
subscribe djgpp-digest-daily
@end quotation
or
@quotation
subscribe djgpp-digest-weekly
@end quotation
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.
@paragraph{}
You can also subscribe to DJGPP-related mailing lists @www{through DJ
Delorie's WWW server, www.delorie.com/mailing-lists/subscribe.html}.
@paragraph{}
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).
@node Unsubscribing, , Subscribing, Help
@comment node-name, next, previous, up
@section How to unsubscribe from the mailing list
@cindex DJGPP mailing list, how to unsubscribe
@cindex Unsubscribing from the DJGPP mailing list
@cindex Read DJGPP traffic via WWW
@cindex DJGPP mailing list/news group, read via WWW
@quest{Whew! There's too much traffic on the djgpp mailing list (at least
the SysAdmin glaring over my shoulder thinks so@dots{} ;-). How do I
unsubscribe myself?}
@quest{I've been trying for days to unsubscribe from the djgpp mailing
list. What am I doing wrong?}
@ans{} You should send your unsubscribe messages to the @mail{list
server, listserv@@delorie.com} @emph{(not djgpp@@delorie.com!)}, with
the contents being just this:
@quotation
unsubscribe djgpp
@end quotation
When you unsubscribe, that stops @emph{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.
@paragraph{}
If you think you have waited enough and the messages still keep coming,
write to @mail{listserv administrator, djgpp-request@@delorie.com} and
ask him to help you.
@paragraph{}
You can also unsubscribe yourself from any DJGPP-related mailing list
@www{through DJ Delorie's WWW server,
www.delorie.com/djgpp/mailing-lists/subscribe.html}.
@paragraph{}
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 @www{via World-Wide Web,
www.delorie.com/djgpp/mail-archives/browse.cgi}.
@node New versions, Miscellany, Help, Top
@comment node-name, next, previous, up
@chapter Version 2 vs v1.x
@cindex V2, new features and bug fixes
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.
@menu
* New and improved:: What's new in v2.0?
* Environment:: How v2.0 environment is different from v1.
* Slow development:: When will the next DJGPP version be released?
* Patched libc:: Where to find the best DJGPP C library.
@end menu
@node New and improved, Environment, New versions, New versions
@comment node-name, next, previous, up
@section New features in DJGPP v2
@cindex New features in v2
@quest{What exciting new features will I find in v2 as opposed to v1.x?}
@ans{} 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:
@itemize @bullet{}
@item
much faster extender (the free DPMI host) and library functions;
@item
very low memory footprint of the DPMI host below 640KB;
@item
the DPMI server is loaded only once: no more problems with spawning child
programs (e.g., almost unlimited recursive Make's);
@item
ANSI- and POSIX-compliant libraries and header files, which should make
porting Unix programs a lot easier;
@item
support for signals;
@item
387 emulation under DPMI;
@item
graphics which works in @emph{any} setup, including under Windows;
@item
fixes of many bugs in hardware interrupts' and mixed-mode programming
support;
@item
support of long filenames on Windows 9X;
@item
ability to build all of DJGPP without commercial products (like Turbo C
required to compile go32 in v1.x);
@end itemize
@paragraph{}
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.
@node Environment, Slow development, New and improved, New versions
@comment node-name, next, previous, up
@section DJGPP environment in v2.x
@cindex V2.x, new environment
@cindex Run-time environment in v2.x
@cindex DPMI hosts, commercially available
@cindex DJGPP v2.x, alternative DPMI hosts
@pindex CWSDPMI, alternative DPMI hosts
@quest{There's been this talk about v2 and about @samp{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?}
@ans{} In v1.x of DJGPP, the @samp{go32} extender was responsible for the
following:
@itemize @bullet{}
@item
Loading and running the application in protected mode.
@item
Managing protected-mode and virtual memory.
@item
``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.)
@item
Handling of hardware interrupts which happen while the CPU is in protected
mode.
@item
Loading 387 emulator (if required).
@item
Loading the graphics driver and working with VGA bank-switching to create
an illusion of a linear video memory.
@item
Command-line and wild-card expansion in a Unix-like fashion.
@end itemize
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
@samp{QDPMI}, Qualitas @samp{386Max}, MS-Windows 3.X and Windows 9X, OS/2,
even Linux), but DJGPP v2 comes with a free DPMI host called
@samp{CWSDPMI} for those who don't have one already. Loading the
application into protected-mode memory (a function done in v1.x by
@samp{go32}) is handled by a 2KB-long real-mode stub which runs at
start-up, before the application's @code{main} functions is called
(the stub will also load @samp{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.
@paragraph{}
@samp{CWSDPMI} can be loaded as a TSR, even loaded @samp{HIGH} into the
HMA/UMB, which will make applications load much faster.
@node Slow development, Patched libc, Environment, New versions
@comment node-name, next, previous, up
@section Why are new DJGPP versions released so slowly?
@cindex Release schedule, how to influence
@cindex Bugfixes, how to ensure they are done
@cindex Development of DJGPP, how to contribute
@cindex DJGPP release schedule
@quest{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?}
@quest{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??}
@ans{} 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{}.
@paragraph{}
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
@file{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.
@paragraph{}
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
(@pxref{Changing, instructions for submitting changes, How to change a
DJGPP package?}). Please be ready for that review process and don't
take it as a rebuttal.
@node Patched libc, , Slow development, New versions
@comment node-name, next, previous, up
@section Where to find the best C library for DJGPP
@cindex C Library, the latest release
@cindex Library, updated, where to get
@cindex Patched libc, where to find
@cindex libc for DJGPP, patched version
@quest{There's been quite some time since the last DJGPP release. Where
can I get all the latest stuff where the bugs are fixed?}
@quest{I have heard rumors that there's a better C library for DJGPP
available from the net. Where is it?}
@ans{} 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.
@paragraph{}
The single most important component of DJGPP tool-chain that might
suffer from long release schedule is the @code{djdev} package. This
includes the C library, @file{libc.a}, which was written specifically
for DJGPP, and some DJGPP-specific development tools, like @code{redir}
and @code{symify}. However, the latter are usually stable and don't
need too much fixing.
@paragraph{}
A full release of @code{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).
@paragraph{}
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:
@example
gcc -c -O2 foo.c
ar rvs c:/djgpp/lib/libc.a foo.o
@end example
@noindent
(This example assumes that DJGPP is installed in the @file{C:@bs{}DJGPP}
directory; if not, you will need to change the pathname of @file{libc.a}
accordingly.)
@paragraph{}
Patching the library like that requires that you download the DJGPP
library sources, @file{djlsrNNN.zip} (where @file{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.
@paragraph{}
Bug reports regarding the library and patches to fix them are posted
from time to time to @news{comp.os.msdos.djgpp}. In addition, the DJGPP
@www{bug-tracking system, 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 @code{patch} utility which is available @ftp{from the DJGPP sites,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2gnu/pat@value{pat-version}b.zip}.
@paragraph{}
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 @file{libc.a} with all the patches. Every patch has
a short description, in case you'd like to decide whether it's for you.
@paragraph{}
The patched library was created by @mail{Tom Demmer,
Demmer@@LStM.Ruhr-Uni-Bochum.De}. @mail{Nate Eldredge,
nate@@cartsys.com} is the current maintainer, and the space available
for FTP is courtesy of @mail{A. Sinan Unur, sinan.unur@@cornell.edu},
on his server. The patched library is available @www{via WWW,
www.cartsys.com/eldredge/djgpp-patches.html} and @ftp{by ftp,
www-leedr.arme.cornell.edu/pub/djgpp-patches/}. Be sure to read the
file @file{ftp.message.txt} when using the FTP server above. The file
@file{README} explains how the patched library can be downloaded and
used.
@paragraph{}
@cindex Library compiled for debugging/profiling
@cindex Profiling, library functions
@cindex Debugging, library functions
The above site also includes two additional versions of the C library:
one compiled with the @samp{-g} switch and the other compiled with the
@samp{-pg} switch to GCC. These are handy if you need to debug library
functions and profile them, respectively.
@node Miscellany, About, New versions, Top
@comment node-name, next, previous, up
@chapter Miscellany
This chapter is a hodgepodge of questions which don't belong to any of
the other chapters.
@menu
* g++.exe:: Unzip complains about it on DOS.
* Changing:: How to change any DJGPP package?
* Samples:: Where to find sample/ported code for DJGPP?
* Symlinks:: Yes, DJGPP allows them (well, almost@dots{})
* DPMI Spec:: Where to look for DPMI specifications.
* WWW:: The DJGPP Web site.
* Upload:: Where to upload your DJGPP packages.
* Cross-DJGPP:: You can use DJGPP for cross-development.
* 0xfe+0x20:: Is this a bug?
* Struct size:: What is the size of a struct under DJGPP?
* Struct packing:: C@t{++} compiler doesn't pack structs.
* Int 24h:: Catching those ``Abort, Retry'' messages.
* go32-v2:: What is go32-v2 for?
* DXE:: What are those @file{.dxe} files?
* LFN:: LFN support had some subtle bugs in v2.0.
* Missing separator:: What does Make mean by that?
* Modification time:: Make says file time is in the future@dots{}
* Numeric tails:: How to turn them off.
* Zoneinfo:: What's in that @strong{zoneinfo/} directory?
* dev directory:: Don't use it!
* ELF vs COFF:: Why doesn't DJGPP switch to ELF object format?
* Random numbers:: How to get them, and how to seed them.
* Lexicon:: What are all these buzzwords you are using?
* void main:: Is this okay in a C program?
* FAQ format:: How to convert this FAQ to other formats.
@end menu
@node g++.exe, Changing, Miscellany, Miscellany
@comment node-name, next, previous, up
@section Unzipping gppNNb.zip complains about g++.exe
@pindex g++.exe, unzip complains on DOS
@cindex Unzipping and running g++.exe produces an error message
@quest{When I unzip the C@t{++} compiler distribution in gppNNb.zip, the
unzip program complains about something called @file{g++.exe}. What
should I do?}
@ans{} If you install DJGPP on anything but Windows 9X, just ignore that
error message and use @file{gpp.exe} or @file{gxx.exe} to compile
C@t{++} programs. @file{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@t{++} compiler is called @samp{g++}. All @file{g++.exe}
does is just to run @samp{gxx} or @samp{gpp}. So you don't lose much by
not having it.
@paragraph{}
If you @emph{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
@samp{g++}. To enable LFN support, set @samp{LFN=y} in the environment.
@node Changing, Samples, g++.exe, Miscellany
@comment node-name, next, previous, up
@section How to change a DJGPP package?
@cindex Changing GNU/DJGPP programs
@cindex GNU packages, how to change
@cindex Recompiling GCC
@cindex Known bugs in DJGPP, how to browse
@cindex Bugs, how to browse a list of known DJGPP problems
@cindex Bug report, how to submit
@cindex Bug-tracking system for DJGPP
@cindex Patches for DJGPP, how to submit
@pindex GCC, recompiling
@pindex Sed requires floating point
@pindex Make requires floating point
@quest{I want to change cc1. How do I do this?}
@quest{How do I fix a bug/add a feature to one of the DJGPP programs?}
@quest{How should I produce patches for DJGPP programs I want to submit,
and to whom should I submit them?}
@ans{} First, get the sources. These are called @file{*s.zip} in the
DJGPP distribution. The C Library sources are in
@file{djlsr@value{djgpp-version}.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:
@example
em1934s1.zip
em1934s2.zip
em1934s3.zip
@end example
@paragraph{}
All sources are shipped in ready-to-build form. Any diffs that come
with the source distribution, like the files called @file{DIFFS}, have
already been applied, and any configuration scripts and/or batch files
have been run.
@paragraph{}
Next, try to build the program without changing it. Look for a file
called @file{README.dos} or @file{README.djgpp}: it should explain the
build procedure and list any optional packages you need to install for
that.
@paragraph{}
If such a @file{README} file is unavailable, you will have to poke
around and figure things out for yourself; here are some hints to help
you out:
@itemize @minus{}
@item
A file called @file{Makefile} or @file{makefile} probably means you
could just type @kbd{make}.
@item
Some packages will have a @file{CONFIGUR.BAT} file, possibly in a
subdirectory called @file{djgpp/} or @file{pc/}; if so, run it first.
@item
If there is a @file{MAKE.BAT} file, run it; if not, look for a file
named @file{MAKEFILE.DJ} or @file{MAKEFILE.DJG}; sometimes these will be
in a subdirectory called @file{dos/}, or @file{msdos/}, or @file{pc/}.
If there is such a file, then type, e.g., @kbd{make -f makefile.djg}, if
not, just say @kbd{make} and see what happens.
@end itemize
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.
@paragraph{}
After you've successfully built the program, make your fixes and build
the program the same way you did before.
@paragraph{}
Note that generally to build these programs, you must have the @ftp{GNU
Make program,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2gnu/mak@value{mak-version}b.zip},
installed, and some makefiles require that you install additional
development utilities, like the @ftp{@sc{sed} editor,
@SimTel{}/pub/simtelnet/gnu/djgpp/sed@value{sed-version}b.zip}.
Sometimes the makefiles won't even run under @file{COMMAND.COM} (they
require a smarter shell). In that case, either get a better shell, or
convert the makefile to be runnable by @file{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
@samp{-n} switch and see what it would have done.
@paragraph{}
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, @ref{Emulation, FP
Emulation, Floating-point code without 80387}. 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.
@paragraph{}
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 @www{list of known bugs, www.delorie.com/djgpp/bugs/}. If
your bug is not there, you can later submit it to the bug-tracking
system.
@paragraph{}
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.
@paragraph{}
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.
@paragraph{}
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 @file{djdevNNN.zip} distribution
should be sent to @DJ{}. If you don't know who maintains a particular
package or port, post the patches to @news{comp.os.msdos.djgpp}, since
the maintainer is most probably reading that group.
@paragraph{}
To generate a patch, run the @code{diff} program (from GNU Diffutils,
@file{v2gnu/dif@value{dif-version}b.zip}) on the old and the new version
of a source file. For example:
@smallexample
diff -c src/libc/dos/dos/int86.old src/libc/dos/dos/int86.c >int86.dif
@end smallexample
@noindent
The file @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 @samp{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.
@paragraph{}
Observing the following guidelines when creating the patch will make
your patches easy to apply:
@itemize @bullet{}
@item
Always use the @samp{-c} switch to @code{diff}, and @strong{never} use
@samp{-c} with an argument that is less than 3 (for example, do
@emph{not} use @samp{-c2}).
@item
Invoke @code{diff} from the root of the DJGPP installation, i.e. from
the directory where you keep the @file{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 @code{patch} utility.
@item
Always use @emph{forward} slashes in pathnames. Backslashes will work
on DOS/Windows, but some packages are maintained on Unix machines, where
@code{patch} doesn't understand backslashes. In particular, DJ Delorie
maintains DJGPP on a Unix box.
@item
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 @file{foo.old} or
@file{foo.bak}; see the example above.
@item
Do @strong{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.
@item
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 @file{djlsrNNN.zip}
distribution follow his distinct style (that style is quite obvious from
the sources, but if you are unsure, ask DJ).
@item
You should @strong{never} use any switches that let @code{diff} ignore
whitespace, like @samp{-b} or @samp{-w}. In most cases, patches
generated with these switches will fail to apply.
@end itemize
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 @file{.txh} file
with its docs), although you are under no obligation to do that.
@node Samples, Symlinks, Changing, Miscellany
@comment node-name, next, previous, up
@section Where to find sample DJGPP code or a package ported to DJGPP?
@cindex DJGPP, sample code
@cindex Packages, ported to DJGPP
@cindex Sound Blaster code for DJGPP
@cindex Timer interrupts code for DJGPP
@cindex TCP/IP library for DJGPP
@cindex GUI libraries for DJGPP
@cindex X emulation for DJGPP
@cindex GNU development utilities, port to DJGPP
@cindex Turbo Vision, DJGPP port
@cindex Game programming, libraries and techniques for DJGPP
@cindex VGA Mode-X graphics for DJGPP
@cindex RCS port to DJGPP
@cindex Development environments for DJGPP
@cindex Dynamically loaded code for DJGPP
@cindex Multitasking packages for DJGPP
@cindex Asynchronous communications packages for DJGPP
@cindex Network interface libraries for DJGPP
@cindex Winsock interface for DJGPP
@pindex RCS port to DJGPP
@pindex DLM, a facility to load code at run time
@pindex Pthreads for DJGPP
@pindex LWP multitasking for DJGPP
@pindex Boot loader for an operating system
@pindex BCSERIO, async communications package for DJGPP
@quest{Where can I find an example of XXXX / a package doing YYYY ?}
@ans{} @mail{Salvador Eduardo Tropea (SET), salvador@@inti.gov.br}
maintains a @www{DJGPP Web Ring page,
www.geocities.com/SiliconValley/Vista/6552/dlinks.html}. @DJ{}
offers another very large collection of @www{DJGPP-related links,
www.delorie.com/djgpp/dl/elsewhere.html}.
@paragraph{}
Here is a list of places you might look into for examples of frequently
needed code fragments, or for packages people keep asking about:
@itemize @bullet{}
@item
Interrupt-driven support of peripheral devices and hooking hardware
interrupts:
@itemize @minus{}
@item
The Allegro library is an excellent place to look for code that install
hardware interrupt handlers and handles several peripheral devices.
@item
@mail{Alaric B. Williams, alaric@@abwillms.demon.co.uk} maintains a
library of utility functions and example handlers, useful for writing
@www{hardware interrupt handling code,
www.abwillms.demon.co.uk/prog/index.html}.
@item
@mail{Bill Currie, bill@@tanihwa.tssc.co.nz} wrote examples of
@ftp{interrupt handlers,
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.
@item
@mail{Martynas Kunigelis, martynas.kunigelis@@vm.ktu.lt} donated a
tutorial and a working @ftp{code that installs a handler for the
hardware keyboard interrupt 09h,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2tk/mkkbd3.zip} that can
also serve as a good example of handling interrupts.
@item
you can look at the latest version of @ftp{Sound Blaster support library
at Oulu,
x2ftp.oulu.fi/pub/msdos/programming/djgpp2/sb05_dj2.zip} or @ftp{on
DJGPP server, ftp.delorie.com/pub/djgpp/contrib/sb05_dj2.zip}; this
is maintained by @mail{Joel Hunter, jhunter@@kendaco.telebyte.net}.
@item
check out the package available from SimTel.NET that @ftp{hooks the
timer interrupt, @SimTel{}/pub/simtelnet/msdos/c/pctime14.zip}.
@item
if you need a serial communications package, check out the @ftp{SVAsync
library,
ftp.delorie.com/pub/djgpp/contrib/svasync.zip}.
@item
another package for serial communications, called @sc{bcserio}, was
written by @mail{Bill Currie, bill@@tanihwa.tssc.co.nz}. @sc{bcserio}
is available @www{from Bill's home page,
www.tssc.co.nz/~bcurrie/serio.zip}.
@item
if you need serial communications from programs that use the Allegro
library, try DZComm, which is available from the @file{v2tk/allegro}
directory on the usual DJGPP sites.
@end itemize
@item
Network support libraries:
@itemize @minus{}
@item
for TCP/IP, check out the WATTCP library, which is available @ftp{from
its home,
dark.uwaterloo.ca/pub/wattcp/tcplib-dj200/tcplib-dj200.1.tar.gz}, or
@ftp{from a Europe mirror, 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.)
@item
as part of the DOS Lynx port done by @DJ{}, he ported the WATTCP library
as well; that port is available @ftp{from DJ's server,
ftp.delorie.com/pub/dj/lynx26s.zip}.
@item
programs which run on Windows 9X can use the Winsock services built into
Windows to establish TCP/IP connections; a C@t{++} interface to Winsock 1
was @www{written by Dan Hedlund, triangle.dyn.ml.org/wsock/}.
@item
another Winsock library is @samp{libsocket}, originally developed by
@mail{Indrek Mandre, indrek@@warp.edu.ee}, currently maintained by
@mail{R. Dawe, rd5718@@bristol.ac.uk}. The latest version (0.7.3, as
of this writing) is available @www{from the libsocket home page,
libsocket.home.ml.org/}, and via FTP @ftp{from the DJGPP archives,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2tk/lsck073b.zip}. This currently
doesn't support the newer Winsock2 VxD which is part of Windows 98.
@item
yet another version of Winsock interface is available at @www{Brennan
Underwood's site, www.rt66.com/~brennan/djgpp/}.
@item
if you need to program an IPX interface, you can get started by
downloading @www{examples of IPX programming,
www.rt66.com/~brennan/djgpp/jonipx.zip}, and also read the @www{IPX Web
page, www.ladder.org/ddr/ipx.html}.
@end itemize
@item
Dynamically loaded code:
@itemize @minus{}
@item
Check out the DLM (Dynamic Link Modules) environment for DJGPP, written
by @mail{Ilya Ryzhenkov, orangy@@inetlab.com}, available from the
@www{DLM home page, www.iis.nsk.su/orangy/dlm/}.
@item
A dynamic linker for DJGPP, called DLX, is available @ftp{from the DJGPP
sites, @SimTel{}/pub/simtelnet/gnu/djgpp/v2tk/dkx291.zip}.
@end itemize
@item
X library:
@itemize @minus{}
@item
the @ftp{Xlibemu library, asterix.inescn.pt/pub/PC/X/} includes
@samp{Xt} and @samp{Xmu} toolkits, a 3D version of the @samp{AW} toolkit,
a few demo applications (e.g. @samp{xmine}), and can be used to compile
@samp{Tcl/Tk} and GNU Emacs with X support. Xlibemu is based on
X11R5 and was originally developed by @mail{Antonio Costa,
acc@@asterix.inescn.pt} for DJGPP v1.x. It is also available @ftp{on an
alternative site, ftp.dei.isep.ipp.pt/pub/pc/djgpp/etc/X/} and @ftp{on
the DJGPP server, ftp.delorie.com/pub/djgpp/contrib/xlibemu/}.
@item
there are also the @ftp{Xlib and Xt libraries for the Quarterdeck's DV/X
environment, @SimTel{}/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.
@end itemize
@item
Ports of various GNU utilities not included in DJGPP:
@itemize @minus{}
@item
Many of these are now part of DJGPP, so first look on SimTel.NET mirrors
@ftp{with rest of DJGPP,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2gnu/}.
@item
@mail{Marc Singer, elf@@netcom.com} maintains a DJGPP port of RCS, the
@ftp{Revision Control System, ftp.netcom.com/pub/el/elf/rcsdos/}.
@end itemize
@item
GUI libraries:
@itemize @minus{}
@item
@sc{sword} (the System of Windows for the ORganization of the Desktop)
is a Graphic User Interface library made with C@t{++} objects, written and
maintained by @mail{Eric Nicolas, nicolas@@JUPITER.saclay.cea.fr}. The
latest version 2.50 is available from the @ftp{v2tk directory,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2tk/} as sw21_*.zip. @sc{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.
@item
JPTUI is an object-oriented textual user interface, written by
@mail{Jean-Pierre Delprat, jpdelprat@@teaser.fr}. It is designed for
C@t{++}, and supports several languages besides US English. You can get
@ftp{JPTUI from SimTel.NET or any of its mirrors,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2tk/jptui4jd.zip}.
@item
the BCGUI package, written by @mail{Bill Currie,
bill@@tanihwa.tssc.co.nz}; you can get it from Bill upon request.
@item
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 @www{TVPlus site,
www.zeta.org.au/~grove/tvhome.html}.
@item
Another port of TVision was done by @mail{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.
@item
A Turbo Vision like library for plain C, called C-Desktop, by
@mail{Brett Porter, blp01@@uow.edu.au}, is available from DJGPP sites
@ftp{on SimTel.NET mirrors,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2tk/cdesk100.zip}.
@item
Another GUI library is XView-PC GUI interface, maintained by
@mail{Antonio Carlos M. de Queiroz, acmq@@coe.ufrj.br}. XView-PC is
available @www{via the Web, www.coe.ufrj.br/~acmq/xview_pc.html} and
also @ftp{via the FTP transfer, coe.ufrj.br/pub/acmq/xv_pc18a.zip}.
@end itemize
@item
Game programming:
@itemize @minus{}
@item
The best library for DOS game programming is the @ftp{Allegro
game programming library,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2tk/alleg@value{alleg-version}.zip},
written and maintained by @mail{Shawn Hargreaves,
Shawn@@talula.demon.co.uk}; also available @www{from Allegro
home page, www.talula.demon.co.uk/allegro/}. @www{Allegro is ported to
X, www.canvaslink.com/allegro/xwinallegro/}. A tutorial for game
programming, called Allegro Vivace, was written by @mail{George Foot,
george.foot@@merton.oxford.ac.uk}, and is available
@www{from George's home page, www.canvaslink.com/gfoot/vivace/}.
@item
Also try @ftp{Jlib,
x2ftp.oulu.fi/pub/msdos/programming/djgpp2/jlib_NNN.zip} written by
@mail{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 @www{Jlib Web page,
www.wave.co.nz/pages/jpg/jlib/}, for the latest developments.
@cindex DirectX programming
@cindex OpenGL programming
@cindex Mesa programming
@item
Another popular library for game development is MGL, the
@dfn{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 @ftp{from SciTech's FTP site,
ftp.scitechsoft.com/devel/beta/dj20lib.zip}.
@item
The Mesa library itself supports DJGPP and is available @www{from the
Mesa home page, www.ssec.wisc.edu/~brianp/Mesa.html}.
@item
Yet another package that supports DirectX 5 for DJGPP and RSXNTDJ is
available @www{via the Web, bbs.para.co.kr/~bng/drdx/drdx.html}.
@cindex CD-playing library
@item
If you need to play audio CDs, try the @www{Brennan Underwood's CD
playing library, brennan.home.ml.org/programming/bcd_103.zip}.
@end itemize
@item
VGA graphics:
@itemize @minus{}
@item
@mail{Paul Fenwick, bg914@@FreeNet.Carleton.CA} wrote an X-Mode package
@ftp{Xlib, ftp.delorie.com/pub/djgpp/contrib/xlibdj24.zip} or
@ftp{Xlib at Oulu, x2ftp.oulu.fi/pub/msdos/programming/djgpp2/xlibdj24.zip}.
@item
@mail{Matthew Bentley, mrb8@@waikato.ac.nz} has written a C@t{++} 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 @file{v2tk} directory on DJGPP sites.
@end itemize
@item
Multi-tasking libraries and OS kernels:
@itemize @minus{}
@item
@ftp{Pthreads,
ftp.cs.fsu.edu/pub/PART/PTHREADS/pthreads.zip}, a Posix threads
library, is a portable, standard package supported on many platforms.
@item
The LWP package is a lightweight preemptive multitasking library written
by @mail{Josh Turpen, snarfy@@goodnet.com} for DJGPP. It has an
extremely simple API and is very fast. You can get @www{LWP via the
Web, www.goodnet.com/~snarfy}.
@item
@sc{pdmlwp} is a multithreading package for DJGPP. It is available as
@file{pdmlwpNN.zip} (@file{NN} is a version number) from the @file{v2tk}
directory on the DJGPP sites.
@item
@mail{Bill Currie, billc@@blackmagic.tait.co.nz} has written a COFF boot
loader using DJGPP; you can get this @www{COFF boot loader from Alaric
Williams' Web site, www.abwillms.demon.co.uk/prog/kernel2.zip}.
@item
Palantir is a multitasking kernel for Allegro, written and maintained by
@mail{Dim Zegebart, zager@@post.comstar.ru}. Palantir is available
@ftp{from DJGPP sites,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2tk/allegro/plntr041.zip}.
@end itemize
@item
Development toolkits and packages:
@itemize @minus{}
@item
@cindex Memory allocations, debugging packages
@cindex malloc, debugging
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
@ftp{from the DJGPP sites,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2tk/mss11b.zip}, and supports both C
and C@t{++} programs. MSS was written and is maintained by @mail{Peter
Palotas, blizzar@@hem1.passagen.se}.
@item
Cdecl is a program for translating hairy C and C@t{++} declarations and
type casts into human-readable English. A DJGPP port by Nate Eldredge
is available @www{via FTP,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2apps/cdecl25b.zip}.
@item
@sc{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. @samp{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 @www{LCLint sources
on the Web, larch-www.lcs.mit.edu:8001/larch/lclint.html}.
@item
@sc{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 @ftp{via 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.
@end itemize
@end itemize
@node Symlinks, DPMI Spec, Samples, Miscellany
@comment node-name, next, previous, up
@section How to create symbolic links to programs
@cindex Symbolic links, simulation with DJGPP
@cindex Links, symbolic, simulation with DJGPP
@quest{How do I create symbolic links?}
@quest{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??}
@ans{} 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 @file{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 @file{dj1.exe} and we want to make a link called
@file{dj2.exe} that really calls @file{dj1.exe.} First, generate a stub
under the name @file{dj2.exe.} Next, run @samp{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 @file{dj1}:
@smallexample
C:\USR\BIN> stubify -g dj2.exe
C:\USR\BIN> stubedit dj2.exe runfile=dj1
@end smallexample
Voila! Now, when you run @samp{dj2}, it tells the stub to load the image
of @samp{dj1}, but pass ``dj2'' in @code{argv[0].}
@paragraph{}
If you use the DJGPP port of GNU Fileutils 3.13 or later, the @samp{ln}
program there can do the above steps for you if you say this (like on
Unix):
@example
ln -s dj1.exe dj2.exe
@end example
@node DPMI Spec, WWW, Symlinks, Miscellany
@comment node-name, next, previous, up
@section Where to find the DPMI specification?
@cindex DPMI, what it is
@cindex DPMI spec, where to get it
@quest{What is this DPMI thing you are all talking about?}
@quest{Where can I find the specifications for the DPMI functions?}
@ans{} DPMI, the @dfn{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. @xref{ASM GPF, restrictions of protected
mode, Converted code GP Faults!}, for more details.
@paragraph{}
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.
@paragraph{}
You can find the DPMI 0.9 spec by anonymous ftp to one of the following
sites:
@itemize @minus{}
@item
@ftp{At the Quarterdeck ftp site,
ftp.qdeck.com/pub/general/dpmispec.zip}.
@item
@ftp{At Oulu,
x2ftp.oulu.fi/pub/msdos/programming/specs/dpmispec.arj}.
@item
The DPMI 1.0 specs are available by anonymous ftp from the @ftp{Intel
anonymous ftp site, ftp.intel.com/pub/IAL/software_specs/dpmiv1.txt}
(the file @file{dpmip1.zip} at the same location is the PostScript
version of this spec), and also @ftp{at the Oulu site,
x2ftp.oulu.fi/pub/msdos/programming/specs/dpmi100.zip}.
@item
A paper copy of the DPMI specifications can be ordered from Intel as
document number 240977-001.
@item
Some information about the DPMI API is also found in the @ftp{Ralf Brown's
Interrupt List,
@SimTel{}/pub/simtelnet/msdos/info/inter@value{inter-version}c.zip}.
Look at the functions of Interrupt 31h, or search the files for the word
@samp{DPMI}.
@item
The DJGPP Web server allows you to use WWW to @www{browse the DPMI spec
on-line, www.delorie.com/djgpp/doc/dpmi/}.
@end itemize
@node WWW, Upload, DPMI Spec, Miscellany
@comment node-name, next, previous, up
@section The DJGPP Web site.
@cindex Web site for DJGPP
@cindex WWW services for DJGPP
@cindex DJGPP, history of the project
@cindex History of DJGPP
@quest{Where is the DJGPP Web site?}
@ans{} Yes, DJGPP has its own home on the Internet, set up and maintained
by (who else?) @DJ{}. 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 @www{the story of DJGPP genesis,
www.delorie.com/djgpp/history.html}.
@paragraph{}
To visit, point your browser to @www{the DJGPP Web site,
www.delorie.com/djgpp/}.
@node Upload, Cross-DJGPP, WWW, Miscellany
@comment node-name, next, previous, up
@section Where to upload your contributions to DJGPP
@cindex DJGPP software, where to upload
@cindex Uploading DJGPP software
@quest{I wrote a program using DJGPP. How can I make it available to
others?}
@quest{I found and corrected a bug in one of the programs distributed with
DJGPP. Where should I put it?}
@ans{} If the program/patches are small enough, consider posting it to
the mailing list or the @news{comp.os.msdos.djgpp}. Please do
@strong{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.
@paragraph{}
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 @ftp{DJ Delorie's FTP server,
ftp.delorie.com/incoming/}. This directory is write-only, and it gets
purged every couple of days, so be sure to write to @DJ about your upload;
he will then move it to the @file{/pub/djgpp/contrib} directory.
@paragraph{}
If you decide to upload, please send mail to the @samp{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 @samp{djgpp-announce} list because they want to get such
announcements and nothing else.)
@paragraph{}
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 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.
@paragraph{}
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.
@node Cross-DJGPP, 0xfe+0x20, Upload, Miscellany
@comment node-name, next, previous, up
@section DJGPP as cross-compiler
@cindex DJGPP as cross-compiler
@cindex Cross-compiling with DJGPP
@cindex 68K targets, cross-compiling with DJGPP
@cindex Motorola 68K targets, cross-compiling with DJGPP
@cindex Linux-to-DOS cross-compiling with DJGPP
@cindex Unix-to-DOS cross-compiling with DJGPP
@quest{I want to use DJGPP as a cross-compiler for Motorola 68K targets.
How should I proceed about this?}
@quest{I want to build GCC as a Unix-to-DOS cross-compiler. What should I
do?}
@ans{} If you want a cross-compiler for m68k on a DOS machine, you need
DJGPP configured as @samp{host=i386-go32}, and @samp{target=m68k-coff.}
Such a package @ftp{is already available,
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 @mail{Jim
Karpinski, jk55@@cornell.edu}. You can also try to contact @mail{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@t{++}:
the compiler is included, but the libraries, including @file{libstc++}
and @file{libg++}, and the C@t{++} headers are missing, so even
@code{cin} and @code{cout} don't work.
@paragraph{}
A @www{Win32-hosted gcc-m68k, 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. @xref{Windows apps, the description of the Cygnus project,
MS-Windows applications and DJGPP}, for more details about the Cygwin32
port.
@paragraph{}
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:
@enumerate
@item
Download the cross-compiler toolkit
@file{v2/djcrx@value{djgpp-version}.zip} from the usual DJGPP sites.
@paragraph{}
@item
Unpack @file{djcrx@value{djgpp-version}.zip} on the Unix machine using
@samp{unzip -a}.
@paragraph{}
You @strong{must} use the @samp{-a} switch, to force @code{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.
@paragraph{}
@code{unzip} is available in source form from many FTP sites.
@paragraph{}
@item
Link or move the files in the @file{cross} directory to the top-level
directory, where you unzipped @file{djcrxNNN.zip}.
@paragraph{}
@item
Download the latest GCC and Binutils distributions from your favorite
GNU FTP site.
@paragraph{}
The main GNU site is @ftp{at ftp.gnu.org, ftp.gnu.org/pub/gnu/}.
@paragraph{}
@item
Unpack GCC and Binutils from the same directory where you unzipped
@file{djcrxNNN.zip}.
@paragraph{}
@item
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).
@paragraph{}
@item
Follow instructions in the file @file{cross/install} that was unpacked
from @file{djcrx@value{djgpp-version}.zip} to build and install the
cross compiler.
@end enumerate
The cross-compiler you build is installed as @code{dos-gcc}, so to
compile programs with it, use @code{dos-gcc} rather than @code{cc} or
@code{gcc}, or set @samp{CC=dos-gcc} when invoking Make.
@paragraph{}
The file @file{cross/readme} has some usage info for @code{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.
@paragraph{}
Another alternative is the RPM (@dfn{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 @mail{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
@ftp{from Redhat site,
ftp.redhat.com/pub/incoming/djgpp-2.1-1.i386.rpm}; the @ftp{sources are
also available, ftp.redhat.com/pub/incoming/djgpp-2.1-1/src.rpm}.
@node 0xfe+0x20, Struct size, Cross-DJGPP, Miscellany
@comment node-name, next, previous, up
@section GCC says ``garbage at end of number''
@cindex Garbage at end of number, GCC message
@pindex GCC says ``garbage at end of number''
@quest{There is a severe bug in GCC: it says ``garbage at end of
number'' for this line:}
@example
i = 0xfe+0x20;
@end example
@paragraph{}
@emph{Ain't it silly that such a great compiler would fail so miserably?}
@ans{} That's not a bug, that's a feature of the @emph{ANSI C language
definition.} By ANSI rules, the above expression is a single
@dfn{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 @samp{-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).
@paragraph{}
Judging by the published draft, this is unchanged even in the
forthcoming C9X standard.
@node Struct size, Struct packing, 0xfe+0x20, Miscellany
@comment node-name, next, previous, up
@section What should sizeof (struct xyzzy) return?
@cindex Size of a struct under DJGPP
@cindex Struct, size in bytes under DJGPP
@cindex Structure padding
@cindex Packing the structs
@cindex Reading structs from disk files
@cindex Reading an int from a binary file
@cindex struct reading from a disk file
@cindex sizeof, result when called on a structure
@quest{When I call @samp{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@t{++} I always get the correct result. Is it a bug in GCC?}
@quest{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?}
@ans{} 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:
@example
struct my_struct @{
char name[7];
unsigned long offset;
double quality;
@};
@end example
To make such a struct use the least number of bytes, rearrange the
members, like this@footnote{
Note that this still allows the struct to be padded at the end.}:
@example
struct my_struct @{
double quality;
unsigned long offset;
char name[7];
@};
@end example
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 @code{__attribute__((packed))} extension
of GCC (@extref{Type Attributes, the Gcc docs, gcc, GNU C/C++ Manual,
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.
@paragraph{}
Beginning with version 2.7.0, GCC has a command-line option
@samp{-fpack-struct} which causes GCC to pack all members of all structs
together without any holes, just as if you used
@code{__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 @strong{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:
@example
struct @{
char name[7];
unsigned long offset;
double quality;
@} __attribute__ ((packed));
@end example
However, note that the latter will only work when you compile it as a C
source; C@t{++} 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 @strong{certain}
it won't be ever compiled as a C@t{++} source.
@paragraph{}
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 @code{sizeof struct foo}
to read and write a structure.
@paragraph{}
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 @code{int} is 16-bit wide in most
DOS-based compilers, but in DJGPP it's 32-bit wide.
@paragraph{}
The best, most robust and portable way to read and write structs is
through a @code{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 @code{offsetof} macro comes in handy in
many such cases.
@node Struct packing, Int 24h, Struct size, Miscellany
@comment node-name, next, previous, up
@section C@t{++} doesn't pack structs!
@cindex Structure packing, C@t{++} bug
@cindex Packed structs, C@t{++} bug
@cindex C@t{++} programs, problems with packed structs
@pindex GCC doesn't pack structs in C@t{++} programs
@quest{When I use @code{struct ffblk} from the header @file{dir.h} in a
C@t{++} program, I get garbage in some members of the structure!}
@ans{} There is a known bug in GCC 2.7.2: the C@t{++} compiler effectively
ignores the @code{__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 @code{#pragma
pack}, like this:
@example
#ifdef __cplusplus
#pragma pack(1)
#endif
.
.
.
#ifdef __cplusplus
#pragma pack()
#endif
@end example
@node Int 24h, go32-v2, Struct packing, Miscellany
@comment node-name, next, previous, up
@section How to avoid ``Abort, Retry, Fail'' messages
@cindex Interrupt 24h handling
@cindex Int 24h crashes DJGPP programs
@cindex harderr function, emulating under DJGPP
@cindex Critical error handling in DJGPP
@cindex Program crashes because of Int 24h
@cindex Program crashes accessing empty floppy/CD-ROM drives
@pindex QDPMI crashes DJGPP programs when they cause Int 24h
@pindex CWSDPMI doesn't support hooking Int 24h
@quest{How do I write a program that accesses floppy and CD-ROM drives,
but avoids popping that ``Abort, Retry, Fail?'' message from DOS?}
@quest{Other DOS compilers supply a function named @code{harderr} or
@code{_harderr} to hook the critical-error interrupt 24h, but DJGPP
doesn't seem to have these...}
@ans{} 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 @kbd{A} in response to that prompt. The default handler under
most DPMI servers will just set @sc{al} register to 3 and do an
@code{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.
@paragraph{}
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 (@pxref{Hardware interrupts, how to set an interrupt
handler, How to hook hardware interrupts}), 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.
@paragraph{}
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
@code{getmntent} (@extref{getmntent, getmntent, libc.inf, libc.a
reference, 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
@code{getmntent} from the @ftp{library source distribution,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2/djlsr@value{djgpp-version}.zip}, or
from the @www{zip picker, www.delorie.com/djgpp/dl/ofc/}.
@node go32-v2, DXE, Int 24h, Miscellany
@comment node-name, next, previous, up
@section What is that @file{go32-v2.exe} program?
@cindex Invoking v2 programs from v1.x programs
@cindex Spawning v2 programs from v1.x programs
@pindex go32-v2 usage
@quest{What is go32-v2 for?}
@ans{} The @code{go32-v2} program does the following:
@itemize @bullet{}
@item
With no command-line arguments, it prints the available physical and
virtual memory, much like @code{go32} did in v1.x.
@item
It can run unstubified v2 COFF images, like this:
@example
go32-v2 myprog
@end example
@item
If you rename it to @file{go32.exe} and put on your @code{PATH} before
the v1.x @file{go32.exe}, it can also run a v1 COFF images, by loading
the v1.x @code{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 @code{go32-v2} (since it found it first on the PATH) which knows
how to run v2 images, instead the original @code{go32} which cannot.
@end itemize
@node DXE, LFN, go32-v2, Miscellany
@comment node-name, next, previous, up
@section What is DXE?
@cindex DXE description
@cindex DXE docs and examples
@cindex Undefined references, in a DXE
@cindex DXE, undefined references
@pindex DXEGEN, undefined references
@quest{What is a DXE?}
@quest{Can I make a DLL using the DXE support?}
@quest{Where can I find information or examples about writing/loading
the DXE files?}
@quest{Why do I get undefined references when I run @code{dxegen}?}
@ans{} DXE is a limited facility to dynamically load code which is
rarely needed in DJGPP. An example is the floating-point emulator code
(@pxref{Emulation, the details of DJGPP FP emulator, Floating-point code
without 80387}) 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.
@paragraph{}
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 @code{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 @code{_dxe_load} when it loads the DXE, and make the init
routine fill the array with the actual addresses of those ``special''
functions.
@paragraph{}
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).
@paragraph{}
The only place you can find some docs and examples of writing and using
a DXE is in the @ftp{``tests'' archive,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2/djtst@value{djgpp-version}.zip}.
The example there is @emph{exceedingly} simplistic, but then so is the
entire DXE mechanism@dots{}
@node LFN, Missing separator, DXE, Miscellany
@comment node-name, next, previous, up
@section Long Filenames Don't Work!
@cindex LFN problems, in DJGPP v2.0
@cindex long filename support, bugs in DJGPP v2.0
@quest{I cannot make Info find some of its files under Windows 9X...}
@quest{Why does Make behave as if some of the files were not there?}
@ans{} 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 @file{ALongFileName.cc} (because the Makefile tells
it to build @file{ALongFileName.o}), make sure there indeed is such a
file in the directory. Sometimes people use archive tools (like
@code{PKZIP}) that truncate long names, even on Windows 9X, when they open an
archive, which leaves you with names like @file{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 @samp{DJTAR} when you
open @file{.tar.gz} archives, or rename all the files to their original
long names after you open the archive.
@paragraph{}
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 @file{DJGPP.ENV}
does not always work in DJGPP v2.0).
@node Missing separator, Modification time, LFN, Miscellany
@comment node-name, next, previous, up
@section Make says ``missing separator''
@cindex Missing separator, Make error message
@cindex Makefile, first character of every command must be TAB
@cindex TAB, must be the first character of every command
@cindex TABs replaced with spaces by a text editor
@pindex Make error message ``missing separator''
@quest{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?}
@ans{} 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.
@paragraph{}
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.
@paragraph{}
Another, more rare, cause of the above error message is if you use static
pattern rules (with the @code{%} character) incorrectly. Read the
documentation that comes with Make carefully and try to find the error.
@node Modification time, Numeric tails, Missing separator, Miscellany
@comment node-name, next, previous, up
@section Make says ``@file{foo} has modification time in the future''
@cindex Modification time in the future, message from Make
@pindex Make, warning ``file modification time in the future''.
@quest{I keep getting messages about file modification time in the
future when I compile my programs using Make@dots{}}
@ans{} 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.
@paragraph{}
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.
@paragraph{}
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.
@node Numeric tails, Zoneinfo, Modification time, Miscellany
@comment node-name, next, previous, up
@section How to Set Up a Dual DOS/Windows Installation
@cindex Installation, dual, DOS/Windows
@cindex Numeric tails, turning off
@cindex Numeric tails, created by PKUNZIP v2.50
@cindex NameNumericTail
@pindex PKUNZIP v2.50, creates numeric tails
@quest{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?}
@ans{} Such a setup is possible, but it involves a few special actions,
and some vigilance on your part during routine operations.
@paragraph{}
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 @file{~N} to the first 6 characters of the
basename. For example, a file called @file{ALongFileName.LongExtension}
will get a short alias @file{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 @file{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:
@itemize @bullet{}
@item
From the ``Start'' menu select ``Run'' and type @samp{regedit}, to start
the Registry Editor.
@item
Expand the @code{HKEY_LOCAL_MACHINE} branch of the registry until you
see in the left pane an item called
@code{HKEY_LOCAL_MACHINE@bs{}System@bs{}CurrentControlSet@bs{}Control@bs{}FileSystem},
then click on it.
@item
The right pane now shows the list of values assigned to the
@code{FileSystem} key. If you don't see an item there called
@code{NameNumericTail}, select ``New'', ``Binary Value'' from the
``Edit'' menu, then type @samp{NameNumericTail} and it will appear. Now
double-click on @code{NameNumericTail} and enter a value of 0.
@item
Exit @samp{regedit} and restart Windows 9X.
@end itemize
If setting @code{NameNumericTail} to 0 breaks some programs, you can
restore its original setting temporarily, while you run those programs.
@code{NameNumericTail} only affects the short names of new files being
created, it has no effect on the files that already exist.@footnote{
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 @file{PROGRA~1} (the short version of the @file{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 @file{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.
@paragraph{}
For what it's worth, I always run my system with numeric tails disabled,
and I have yet to see a single real problem.}
@paragraph{}
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 @file{.emacs} and
@file{.bashrc}, file names with more than a single dot, like
@file{make-3.77.tar.gz}, or file names which include characters not
allowed by DOS, like @file{libg++.a}.
@paragraph{}
One other problem is to avoid using programs which create numeric tails
even if they are disabled in Windows. One such program is
@samp{pkunzip} version 2.50. Don't use it, if you want to keep your
dual DOS/Windows installation in working order.
@paragraph{}
The most simple method of deciding at boot time which configuration (DOS
or Windows) to start is to edit the (hidden) file @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 @file{MSDOS.SYS} that reads ``BootMenu=0'' to say
``BootMenu=1'' instead, and reboot.
@node Zoneinfo, dev directory, Numeric tails, Miscellany
@comment node-name, next, previous, up
@section What is in that @file{zoneinfo} directory?
@cindex Zoneinfo directory
@cindex TZ variable, how to set
@cindex TZ database updates, where to get
@quest{When I installed DJGPP v2, it created a directory named
@file{zoneinfo} with a lot of small files that take up 3.5MB of my disk
space. What are they for? Can I delete them?}
@ans{} These files exist so that time-related library functions can
correctly calculate the offset between the local time and the @dfn{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.
@paragraph{}
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 @samp{Zip} and want your recipients to be able to
restore the correct time stamps of your files when they unzip them.
@paragraph{}
If you don't care about file time stamps being incorrect in such cases,
you can delete all those files and never look back.
@paragraph{}
You might wonder why we need all these zoneinfo files when the UTC
offset @emph{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 @code{TZ}
environment variable to the file that is pertinent to his/her time zone,
which is easy:
@example
set TZ=c:/djgpp/zoneinfo/israel
@end example
@noindent
@emph{or}
@example
set TZ=c:/djgpp/zoneinfo/us/alaska
@end example
To find the rule suitable for your location, look into the @file{src}
subdirectory of @file{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
@samp{zic}, whose source is available in the
@file{v2/djlsr@value{djgpp-version}.zip} file,
@ignore
@file{v2/djtzs@value{djgpp-version}.zip} file,
@end ignore
with the rest of DJGPP.
@paragraph{}
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
@file{zoneinfo} directory which comes with DJGPP is based on this
database, but if you want the latest rules, you can @ftp{download them
from the net, elsie.nci.nih.gov/pub/} as @file{tzdata*.tar.gz};
@file{tzcode*.tar.gz} in the same directory includes the programs that
can be used to generate the offset tables from their source in
@file{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.
@paragraph{}
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.
@paragraph{}
@node dev directory, ELF vs COFF, Zoneinfo, Miscellany
@comment node-name, next, previous, up
@section The Secrets of the /dev/ Directory@dots{}
@cindex /dev/ directory, problems with DJGPP programs
@quest{All DJGPP programs cannot find files in the @file{d:@bs{}dev}
directory, but work okay in other directories. What is going on here??}
@ans{} This is an unfortunate side-effect of the special treatment given
to the @file{@bs{}dev} directory on each drive. DJGPP transparently
supports Unix-style devices such as @file{/dev/null} and
@file{/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
@file{@bs{}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 @file{@bs{}devel}, or to move it down the directory hierarchy, for
example make it @file{d:@bs{}software@bs{}dev}. (The special treatment
is only reserved to the @file{@bs{}dev} directories immediately under
the root of every drive.)
@node ELF vs COFF, Random numbers, dev directory, Miscellany
@comment node-name, next, previous, up
@section How about switching to ELF as DJGPP's object file format?
@cindex ELF, switching DJGPP to
@cindex COFF, why is DJGPP using it
@quest{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?}
@ans{} 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:
@itemize @bullet{}
@item
Changing the binary format requires many changes to several packages
that are central to DJGPP:
@itemize @minus{}
@item
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.
@item
The DJGPP stub loader (@file{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.
@item
All stub-related programs, like @code{go32-v2}, @code{stubify} and
@code{stubedit}, need to be changed as well.
@item
The DJGPP debugger support (functions in the @file{src/debug/} directory
in the @samp{djlsr} distribution) need to be changed to support ELF.
@item
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.
@end itemize
@item
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.
@item
Because of the above, switching to ELF will totally break
back-compatibility with old libraries and object files.
@end itemize
None of the above is a show-stopper, so such a switch @emph{is}
possible. But it is a large project, and without several devoted
volunteers, chances are it will never happen.
@node Random numbers, Lexicon, ELF vs COFF, Miscellany
@comment node-name, next, previous, up
@section How to produce random numbers?
@cindex Random numbers, how to produce
@cindex Seed for random numbers
@cindex Pseudo-random numbers
@cindex @code{rand} and @code{random} functions, comparison
@quest{How do I produce random numbers with DJGPP?}
@quest{I keep getting the same random numbers each time I run my
program. How do I get a different series on every run?}
@ans{} DJGPP has in its library two functions to produce series of
@dfn{pseudo-random}@footnote{
Since these series are computed using a deterministic algorithm, they
are not @emph{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.} numbers: @code{rand} and
@code{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
@code{random} have better qualities than those produced by @code{rand}.
In particular, the least-significant bits in the numbers produced by
@code{random} are much more random than those you get from @code{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 @code{random () % 5}.
However, the DJGPP implementation of @code{rand} is quite good, so when
portability @emph{is} important, you should use @code{rand}.
@paragraph{}
Both @code{rand} and @code{random} return a pseudo-random integer in the
range @code{[0..RAND_MAX]}, where @code{RAND_MAX} is defined in the
@file{stdlib.h} header.
@paragraph{}
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
@dfn{seed}. Two functions provided for this purpose, @code{srand} and
@code{srandom}, will seed the series generated, respectively, by
@code{rand} and @code{random}. You seed the series with a single call
to @code{srand} or @code{srandom}, and then proceed by calling
@code{rand} or @code{random} as usual.
@paragraph{}
A popular way of getting a different seed every run is to use the
current system clock as the seed, like this:
@example
srand (time (NULL));
@end example
If the 1-second granularity of the values returned by @code{time} is not
enough for you (e.g., if you need to generate more than one series every
second), use @code{gettimeofday} or @code{uclock}, or use the values
returned by @code{rand} as an argument to @code{srandom} (or vice
versa).
@node Lexicon, void main, Random numbers, Miscellany
@comment node-name, next, previous, up
@section What are all these buzzwords I see?
@cindex Lexicon for DJGPP documentation
@cindex Jargon, used by DJGPP documentation
@cindex Terminology in DJGPP
@quest{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??}
@ans{} 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 @www{DJGPP Lexicon page,
www.delorie.com/djgpp/doc/lexicon/}. Another excellent resource for
computer-related terminology is the @www{Jargon File,
www.ccil.org/jargon/}, also available from the @ftp{GNU FTP site,
ftp.gnu.org/pub/gnu/} as an Info file and in several other formats.
@node void main, FAQ format, Lexicon, Miscellany
@comment node-name, next, previous, up
@section What should the @code{main} function return in a C program?
@cindex void main, in a C program
@quest{Why does everybody tell me that @code{void main} is bad?}
@quest{If @code{void main} is incorrect, how come the compiler lets it
compile?}
@ans{} The ANSI/ISO C Standard specifies that the @code{main} function
be declared in one of the following two ways:
@example
int main (void);
@end example
@noindent
or
@example
int main (int argc, char **argv);
@end example
In both cases the return type is an @code{int}, and your @code{main}
function should therefore either return an @code{int} or call the
library function @code{exit}, when the program ends.
@paragraph{}
Since the runtime environment assumes that @code{main} returns an
@code{int}, declaring @code{main} with any other return type, including
@code{void}, invites trouble. The compiler might compile such a
program, since the ANSI Standard doesn't @emph{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 @samp{-Wall} switch.
@paragraph{}
To summarize, using @code{void main} is @emph{unsafe} and can
potentially do evil things to your program. It is best to avoid it.
@node FAQ format, , void main, Miscellany
@comment node-name, next, previous, up
@section Generating the FAQ in your favorite format
@cindex FAQ, conversion to different formats
@cindex Conversion of the FAQ to different formats
@pindex MAKERTF, produces the FAQ in RTF format
@pindex INFNG, produces the FAQ in Norton Guides format
@quest{How can I generate the FAQ list in a format I'm used to?}
@ans{} First, I suggest to check whether the FAQ is already available in
your format. The @ftp{FAQ distribution,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2/faq@value{faq-version}b.zip}
includes the Info, plain-ASCII (text), and HTML (one large @file{.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.
@paragraph{}
If you prefer to read the FAQ list as hard-copy, get @file{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. @file{faqNNNp.zip} also includes a @file{.dvi} file
which you can print or view using one of the available DVI drivers and
previewers, such as Ghostscript or @samp{dvivga}.
@paragraph{}
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 @ftp{on SimTel,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2/faq@value{faq-version}s.zip}.
This includes the FAQ sources themselves (written in Texinfo), and all
the auxiliary tools required to produce all the formats in
@file{faqNNNb.zip} and @file{faqNNNp.zip}.
@paragraph{}
Once you download the sources, you will need one or more of the tools
listed below to generate the FAQ list in other formats.
@paragraph{}
A program called @samp{Makertf} can reportedly be used to convert a
Texinfo sources of this FAQ to the @dfn{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 @ftp{from the Microsoft ftp
site, ftp.microsoft.com/Softlib/MSLFILES/HC505.EXE}.
@paragraph{}
A derivative of @TeX{} called PDF@TeX{} can be used to generate a PDF
file from @TeX{} sources. This means that a Texinfo source can also be
submitted to PDF@TeX{}, but I didn't try that. PDF@TeX{} was port to
DJGPP and can be downloaded from its home site @ftp{via FTP,
ftp.cstug.cz/pub/tex/local/cstug/thanh/pdftex-testing/}.
@paragraph{}
There's also a program called @samp{INFNG} that can be used to convert
the Info (@strong{not} Texinfo) version of the FAQ to the Norton Guide
format. @samp{INFNG} is available from @ftp{the DJGPP archives,
@SimTel{}/pub/simtelnet/gnu/djgpp/v2misc/infng100.zip}.
@paragraph{}
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.
@paragraph{}
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).
@paragraph{}
@node About, Topic Index, Miscellany, Top
@comment node-name, next, previous, up
@chapter About this FAQ
Maintainer: @mail{Eli Zaretskii, eliz@@is.elta.co.il}.
@paragraph{}
Copyright @copyright{} 1994, 1995, 1996, 1997, 1998 by @mail{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.
@paragraph{}
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).
@paragraph{}
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:
@display
@mail{John M. Aldrich, fighteer@@cs.net}
@mail{Anthony Appleyard, A.APPLEYARD@@fs2.mt.umist.ac.uk}
@mail{Gurunandan R Bhat, grbhat@@unigoa.ernet.in}
@mail{John Bodfish, bodfish@@austen.notis.com}
@mail{Francois Charton, deef@@pobox.oleane.com}
@mail{Alain CULOS, Alain.Culos@@bigfoot.com}
@mail{Bill Currie, bill@@tanihwa.tssc.co.nz}
@mail{Bill Davidson, bdavidson@@ra.isisnet.com}
@DJ{}
@mail{Tom Demmer, Demmer@@LStM.Ruhr-Uni-Bochum.De}
@mail{Nate Eldredge, nate@@cartsys.com}
@mail{Juergen Erhard, jae@@laden.ilk.de}
@mail{Andy Eskilsson, x-aes@@telelogic.com}
@mail{Jeremy Filliben, prime@@UDel.Edu}
@mail{Peter Gerwinski, peter@@agnes.dida.physik.uni-essen.de}
@mail{Till Harbaum, harbaum@@ibr.cs.tu-bs.de}
@mail{James W. Haefner, Jim@@anolis.bnr.usu.edu}
@mail{Kris Heidenstrom, kheidens@@actrix.gen.nz}
@mail{Koen Van Herck, kvhk@@barco.com}
@mail{Vik Heyndrickx, Vik.Heyndrickx@@rug.ac.be}
@mail{Robert Hoehne, robert.hoehne@@gmx.net}
@mail{Gordon Hogenson, ghogenso@@u.washington.edu}
@mail{Harry Johnston, omega@@es.co.nz}
@mail{Martynas Kunigelis, martynas.kunigelis@@vm.ktu.lt}
@mail{Pieter Kunst, kunst@@prl.philips.nl}
@mail{Y. Lazarovitch, yitzg@@haven.ios.com}
@mail{Alexander Lehmann, lehmann@@mathematik.th-darmstadt.de}
@mail{Marty Leisner, leisner@@sdsp.mc.xerox.com}
@mail{Dave Love, d.love@@dl.ac.uk}
@mail{Randy Maas, randym@@acm.org}
@mail{Cameron Mallory, mallory@@wcug.vwu.edu}
@mail{Colin S. Miller, csmiller@@iname.com}
@mail{Duncan Murdoch, D.J.Murdoch@@bristol.ac.uk}
@mail{Rob Nader, naderr@@topaz.cqu.edu.au}
@mail{Eric Nicolas, nicolas@@JUPITER.saclay.cea.fr}
@mail{Adrian Oboroc, ash@@cinf.usm.md}
@mail{Jan Oonk, jan@@stack.nl}
@mail{Elliott Oti, e.oti@@stud.warande.ruu.nl}
@mail{Bob Paddock, bpaddock@@execpc.com}
@mail{Esa A E Peuha, peuha@@cc.helsinki.fi}
@mail{Walter Prins, prins@@quark.cs.sun.ac.za}
@mail{Steve Salter, salters@@admin.fanshawec.on.ca}
@CWS{}
@mail{Terrel Shumway, Shumw001@@Cerritos.edu}
@mail{Andrew Szymkowiak, aes@@solia.gsfc.nasa.gov}
@mail{Launey Thomas, ljt@@sierrasemi.com}
@mail{Chris Tilbury, C.J.Tilbury@@estate.warwick.ac.uk}
@mail{Ned Ulbricht, nedu@@ee.washington.edu}
@Steve{}
@mail{Santiago Vila, sanvila@@pizarro.unex.es}
@mail{Ronan Waide, waider@@waider.ie}
@mail{Morten Welinder, terra@@diku.dk}
@mail{Anthony Edward Wesley, awesley@@galaxy.anutech.com.au}
@mail{K.B. Williams, Kbwms@@aol.com}
@mail{Mark H. Wood, mwood@@mhw.OIT.IUPUI.EDU}
@end display
@node Topic Index, Program Index, About, Top
@comment node-name, next, previous, up
@chapter 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).
@ifset html
@*
@*
@include concepts.idx
@*
@*
@end ifset
@ifclear html
@printindex cp
@end ifclear
@node Program Index, , Topic Index, Top
@comment node-name, next, previous, up
@chapter 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.
@ifset html
@*
@*
@include programs.idx
@*
@*
@end ifset
@ifclear html
@printindex pg
@end ifclear
@contents
@bye
@c Local Variables:
@c time-stamp-line-limit:15
@c time-stamp-start:"^@set update-date "
@c time-stamp-end:"$"
@c time-stamp-format:"%:d %:b %:y"
@c eval:(require 'time-stamp)
@c eval:(add-hook 'write-file-hooks 'time-stamp)
@c End: