\chapter{GPM-DJGPP}
{\bf\huge 32-bit \gpm\ for DOS}
\section{Introduction}
\gpmdj\ is a port of \gpml\ which runs under {\em DOS}, in 32-bit protected mode.
This version depends on the \goXX\ ``dos-extender'', floating-point emulator
and various utilities that are part of the \djgpp\footnote{\djgpp\ can be
downloaded from {\tt oak.oakland.edu:/pub/msdos/djgpp} and other Simtel20 mirror
sites} distribution.
It requires an IBM compatible PC, equipped with any i386, i486 or Pentium processor.
This version is compatible with \gpml\ apart from the differences noted here.

\section{Installation}
The installation of \djgpp\ is quite separate to the installation of
\gpmdj.  You can do these two installation procedures in either order.

\subsection{Installation of \djgpp}
To install \djgpp, you must do the following:
\begin{itemize}
\item Create a directory to install in, like \verb+C:\DJGPP+\\
  This documentation relates to \djgpp\ Version 1.12.\\
  When \djgpp\ Version 2.0 is available \gpmdj\ will be upgraded.
\item Un-zip these zipfiles in the install directory.
\begin{verbatim}
    C:\DJGPP> unzip386 -o djeoe112.zip  (Minimum runtime stuff)
    C:\DJGPP> unzip386 -o djdev112.zip  (Minimum development stuff)
    C:\DJGPP> unzip386 -o gcc263bn.zip  (The C compiler)
    C:\DJGPP> unzip386 -o bnu252bn.zip  (The assembler, linker etc)
    C:\DJGPP> unzip386 -o gdb412bn.zip  (The debugger)
\end{verbatim}
\item Un-zip optional documentation (a good idea if you have the room)
\begin{verbatim}
    C:\DJGPP> unzip386 -o txi310bn.zip  (Online doc reader INFO.EXE)
    C:\DJGPP> unzip386 -o txi310dc.zip  (Documentation on INFO)
    C:\DJGPP> unzip386 -o djdoc112.zip  (Documentation on go32)
    C:\DJGPP> unzip386 -o gcc263dc.zip  (Documentation on gcc)
    C:\DJGPP> unzip386 -o bnu252dc.zip  (Documentation on as, ld etc)
    C:\DJGPP> unzip386 -o gdb412dc.zip  (Documentation on gdb)
\end{verbatim}
\item Edit your {\tt CONFIG.SYS} file to include something like the following:
\begin{verbatim}
    SHELL=C:\COMMAND.COM C:\ /e:1000 /p
    DEVICE=C:\DOS\HIMEM.SYS
    DEVICE=C:\DOS\ANSI.SYS
    DOS=HIGH
    BUFFERS=10
    FILES=30
\end{verbatim}
  The \verb+SHELL=+ line prevents ``Out of environment space'' errors.\\
  The \verb+FILES=+ line prevents ``Too many open files'' errors.\\
  The \verb+DEVICE=C:\DOS\HIMEM.SYS+ and \verb+DOS=HIGH+ lines make more
  low memory available for programs like the {\bf gpmake} utility that spawn
  multiple copies of \goXX.
  See {\tt README.1ST} for information on supported drivers.
\item Edit your {\tt AUTOEXEC.BAT} file to include at least the following:
\begin{verbatim}
    PATH C:\DOS;C:\DJGPP\BIN;C:\GPM\BIN;
    SET TEMP=C:\DJGPP\TMP
    SET M2LIB=C:\GPM\M2LIB
    SET M2SYM=C:\GPM\M2SYM
    SET GPMEDITOR=EDIT %%
    SET DJGPP=C:/DJGPP/DJGPP.ENV
    SET GO32=ansi driver C:/DJGPP/DRIVERS/VGA.GRD
\end{verbatim}
 The {\tt TEMP, M2LIB, M2SYM} and {\tt GPMEDITOR} environment variables are
 used by gpm and are described fully in Chapter 7 of the Reference Manual.\\
 {\tt DJGPP} points to a file that is used by \goXX\ to load the environment.\\
 {\tt GO32} defines the options for the \goXX\ program.
 For more information on these environment variables see {\tt README.DJ}.
 Note that the utilities that are part of \djgpp\ are \unix\ programs that expect
 forward slashes in path names.  In most situations back slashes will also work
 as \goXX\ recognises both and converts as necessary.
\item Install maintainence releases\\
  Make sure your environment is set before you do this.\\
  For example:
\begin{verbatim}
    C:\DJGPP> \AUTOEXEC
    C:\DJGPP> unzip386 -o dj112m1.zip
    C:\DJGPP> 112m1
    C:\DJGPP> unzip386 -o dj112m2.zip
    C:\DJGPP> 112m2
    C:\DJGPP> unzip386 -o dj112m3.zip
    C:\DJGPP> 112m3
    C:\DJGPP> unzip386 -o dj112m4.zip
    C:\DJGPP> 112m4
\end{verbatim}
\item If you have more than 2MB of extended memory, installing a disk cache
  program will improve performance enormously
\end{itemize}

\subsection{Installation of \gpmdj}
To install \gpmdj, you must do the following:
\begin{itemize}
\item Create a directory to install in, like \verb+C:\GPM+
\item Un-zip the gpm distribution in the install directory.
\begin{verbatim}
    C:\GPM> unzip386 -o gpmdjgpp.zip
\end{verbatim}
\item Set up your {\tt AUTOEXEC.BAT} as shown above.
\end{itemize}

\section{How it all works}
Modula-2 programs written in any of the \unix\ versions of \gpm\ are (apart from
a few minor differences) portable to \gpmdj\ running on a {\em DOS} machine.
This magic is made possible by the \goXX\ program. \goXX\ is 
basically a Turbo-C program that creates a 32-bit flat program arena, into 
which it loads a {\em COFF\/} image file. Look at \verb+DOCS\INTERNAL.DOC+
if you are interested in the gory details.

Your program runs in 32-bit protected mode and you only transfer to real mode
to do file and device I/O, directory and exec services. Screen I/O is done by
special 32-bit mode drivers loaded by \goXX.  There is a significant overhead
in using a {\em DOS} function.  Any parameters have to be copied down to low
memory, the processor put into real mode, the {\em INT\/} 21 performed and then
the whole process reversed.  This is all handled by the low level C language
libraries linked with the Modula-2 libraries by the build process.

To make it possible to create standalone {\em DOS} executables (.EXE files) a 
utility, {\tt coff2exe}, is supplied with \djgpp.  Basically it just prepends
a small program, STUB.EXE, to your {\em COFF\/} binary. You must have
GO32.EXE on your search path because STUB.EXE runs it.

For machines without a floating-point coprocessor, \djgpp\ provides a 387 
emulator that traps FPU instructions and emulates them transparently (apart
from speed of course and some small problems with precision).
If you do not have a coprocessor, then even if your programs do not use 
type REAL, you must still install the emulator, as the gpm startup 
code performs an FPU initilization that otherwise causes \goXX\ to abort.
Install the emulator by including it in the GO32 environment variable.\\
  For example:
\begin{verbatim}
    SET GO32=ansi driver C:/DJGPP/DRIVERS/VGA.GRD emu C:/DJGPP/BIN/emu387
\end{verbatim}

\subsection{Compiling and linking}
As is the case for all current native code versions of \gpm, \gpmdj\ produces
output as assembler.  This is assembled and linked using the FSF utilities
provided in the \djgpp\ distribution.  These utilities are recompilations of
\unix\ sources, and thus expect to be working with {\em COFF\/} format binaries.
\goXX\ provides the standard {\em DOS} response file (\verb+@+file) for giving more
than 128 bytes of command line and also performs wildcard expansion (globbing),
in much the same way as \unix\ shells.

To make the process as transparent as possible for users of \gpmdj, the 
{\bf build} driver automatically runs {\tt coff2exe} on your linked program, 
to create a {\em .EXE\/} file.  The {\em COFF\/} format binary 
(with \unix\ naming convention of no extension) is left behind for debugging 
purposes, as described below.

The \gpm\ compiler and utilities are all written in Modula-2 and have been
bootstrapped with \djgpp.  Thus the binaries supplied with the \gpmdj\
distribution require \goXX\ to run, just as do the programs they create.


\subsection{Using \gpmdj\ under Windows}
\gpmdj\ runs in a text window using DPMI memory.  As a development environment
this is not particularly recommended, as the current \goXX\ has a rather large
low memory footprint (about 120K).  GPMAKE can invoke up to five copies of 
\goXX\ at times so the less things that you have loaded using low memory, the
better.  Now, if you compile a program with say:\\
\verb+    gpmake foo+\\
you may find that the program runs fine outside of Windows, but crashes with
a Stack Fault when run under Windows.  This is because by default \gpm\ uses
EBP as a general register.  See DJGPP.FAQ for an explanation of this, but
it suffices to know that if you want to run a program under Windows always 
compile with the -Nf ({\bf N}o {\bf f}rame optimisations) switch, as in:\\
\verb+    gpmake -Nf foo+


\subsection{Debugging}
{\tt EDEBUG32} is the \djgpp\ debugger.  It is an external 32-bit binary 
that \goXX\ loads alongside your application.  It is fairly primitive,
but can be useful in situations where \gdb\ is unable to run.  Read
\verb+DOCS\EDEBUG32.DOC+ for more information.

The \gdb\ debugger, being a \unix\ utility, operates on the {\em COFF\/}
image file, and must be manually started using \goXX.
It provides source level debugging of your Modula-2 programs.
As an example, in order to compile, build and debug a program 
{\tt foo.mod} the following sequence of commands is required~---
\begin{quote}
{\tt C:> gpm -g foo.mod}\\
{\tt C:> build foo}\\
{\tt C:> go32 -d gdb foo}
\end{quote}
Alternatively, the same effect could be obtained by using {\bf gpmake}~---
\begin{quote}
{\tt C:> gpmake -g foo.mod}\\
{\tt C:> go32 -d gdb foo}
\end{quote}
Note the use of the {\bf --d} flag to \goXX, so as to allow debugging.
\gdb\ works exactly as on \gpml\footnote{Using \gdb\ with \gpm\ is
described in the appendix {\em Debugging with gdb -- getting started.}}, 
except that once the debugged program
has been started, it cannot be restarted from the entry point.  It is thus
necessary to exit \gdb\ and restart it, if the program needs to be 
restarted from the beginning.

\section{Differences from gpm-linux}

\subsection{Different behaviour for build --S}
As well as creating the temporary files {\tt modbase.dcf} and {\tt modbase}, 
{\bf build} for \gpmdj\ creates {\tt modbase.bat}.  In this case {\tt modbase} 
is the response file for the linker script in {\tt modbase.bat}.

\subsection{Signals not caught}
One of the limitations of the current \djgpp\ implementation is that signals
cannot be caught by applications.  The only effect this has on \gpm\ programs
is that the error messages ``divide by zero error'' and ``memory error'' are
not printed.  In these cases \goXX\ prints a similar message before aborting.

\subsection{The DOS specific libraries}
There are two special libraries for \gpmdj.  These are {\tt PcProcesses},
and a special version of the standard {\tt UxFiles} module that understands
{\em DOS} file attributes.

\newpage	%%%%%%%%%%%%%% beware forced newpage %%%%%%%%%%%%%%%%%
\subsubsection*{The PcProcesses Library}
This library provides a mapping to the {\em DOS} system facilities for
spawning of programs. For some programs, these libraries can
replace the facilities provided by {\em UxProcesses}. For example,
the driver programs {\tt build} and {\tt gpm} use the {\em Spawnv}
function to execute the compiler (and, if necessary the editor).
In the \unix\ versions {\em fork, exec} and {\em wait} calls
provide the same functionality.
{\small \begin{verbatim}
(* ========================================================= *)
(* Preliminary library module for Gardens Point Modula       *)
(* ========================================================= *)

FOREIGN DEFINITION MODULE PcProcesses;

  IMPORT IMPLEMENTATION FROM "pcproces.o";

  FROM Types IMPORT SHORTINT;
  FROM SYSTEM IMPORT ADDRESS;
  IMPORT BuildArgs;
  PROCEDURE Spawns(comPath : ARRAY OF CHAR;
                   argStrn : ARRAY OF CHAR) : SHORTINT;
  (* Spawns another process, and waits for return result *)
  (* comPath is name of .exe, .com or .bat executable    *)
  (* argStrn are the additional arguments of the command *)
  (* Result is exit code of the spawned process          *)

  PROCEDURE Spawnv(comPath : ARRAY OF CHAR;
                   argvBlk : BuildArgs.ArgPtr) : SHORTINT;
  (* Spawns another process, and waits for return result *)
  (* comPath is name of .exe, .com or .bat executable    *)
  (* argvBlk are the additional arguments of the command *)
  (* Zero'th element of argvBlk is ignored               *)
  (* Result is exit code of the spawned process          *)

  PROCEDURE System(command : ARRAY OF CHAR) : SHORTINT;
  (* Spawns another copy of the command processor as     *)
  (* specified by the environment variable COMSPEC, this *)
  (* executes the command. Returns non-zero on failure   *)

  PROCEDURE PSP() : ADDRESS;

END PcProcesses.
\end{verbatim} }

The {\tt Spawns} function takes two strings as parameters. The first is the name of
the program or command file to be executed, while the second is the command
line to be passed to it.  The file is found using the normal path search algorithm.
The {\tt Spawns} functions actually builds an argument block
from the two parameters, then chains internally to the underlying {\tt Spawnv}
function.

The {\tt Spawnv} function takes a \unix\ style argument block as a second
parameter.  The type is a pointer to a {\em NIL} terminated array of {\tt Ascii.nul}
terminated character strings.  The module {\tt BuildArgs} provides portable
facilities for manipulating these blocks as abstract data types.
It is normal for the first argument in such an argument block to be the program name.
Note that \djgpp\ replaces the first element of the argument block
with a string containing the full path name of the program. 

{\tt System} works by spawning a copy of the command processor and passing the
command parameter to that program, typically {\tt CMD.EXE}.

{\tt PSP} is included for compatibility with other versions and under \gpmdj\
returns the result of {\tt getuid()}.

\subsubsection*{The DOS version of UxFiles}
This library has differences only in the file modes and permission bits.
The {\tt ReadOnly}, {\tt WriteOnly} and
{\tt ReadWrite} modes open the file in binary mode.  To open a file in 
text mode use the {\tt ReadOnlyText, WriteOnlyText} and
{\tt ReadWriteText} modes.
Carriage-return linefeed pairs are converted to linefeeds on reading
and linefeeds are converted to carriage-return linefeed pairs on output.

{\small \begin{verbatim}
(* ========================================================= *)
(* Preliminary library module for Gardens Point Modula       *)
(* ========================================================= *)

FOREIGN DEFINITION MODULE UxFiles;

  IMPORT IMPLEMENTATION FROM "uxfiles.o";

(*
 * WARNING WARNING: THIS IS THE MSDOS VERSION.  FILE    *
 * PERMISSION BITS ARE DIFFERENT TO THE UNIX VERSIONS   *
 *
 * This module provides the low level interface to the  *
 * UNIX file system, it links to the library <stdio.h>  *
 * The user programs are protected against the UNIX     *
 * identifiers which are introduced in the header file  *)

FROM SYSTEM   IMPORT ADDRESS, BYTE;

TYPE
  File;
  OpenMode = (ReadOnly, WriteOnly, ReadWrite,
              ReadOnlyText, WriteOnlyText, ReadWriteText);

  FilePermissionBits = (rdOnly,hidden,system,volId,subDir,archive);
  FileMode = SET OF FilePermissionBits;

PROCEDURE GetMode( name : ARRAY OF CHAR;
               VAR mode : FileMode;
               VAR done : BOOLEAN);
(* precondition  : name must be a nul-terminated variable
                   array,or a literal string.
   postcondition : if done then mode has permission bits *)
\end{verbatim}
\continue
\newpage
\begin{verbatim}
PROCEDURE SetMode( name : ARRAY OF CHAR;
                   mode : FileMode;
               VAR done : BOOLEAN);
(* precondition  : name must be a nul-terminated variable
                   array,or a literal string.
   postcondition : if done then file has permission bits *)

PROCEDURE Open(VAR f    : File;       (* Open an existing file *)
                   name : ARRAY OF CHAR;
                   mode : OpenMode;
               VAR done : BOOLEAN);

PROCEDURE Create(VAR f    : File;     (* Open a new file *)
                     name : ARRAY OF CHAR;
                 VAR done : BOOLEAN);

PROCEDURE Close(VAR f    :   File;      (* Close a file *)
                VAR done : BOOLEAN);

PROCEDURE Delete(str  : ARRAY OF CHAR;
             VAR ok   : BOOLEAN);

PROCEDURE Reset(f : File);
(* Position the file at the beginning and set to "ReadMode"   *)

PROCEDURE ReadNBytes(f              : File;
                     buffPtr        : ADDRESS;
                     requestedBytes : CARDINAL;
                 VAR read           : CARDINAL);
  (* Read requested bytes into buffer at address *)
  (* 'buffPtr', number of effectively read bytes *)
  (* is returned in 'read'                       *)

PROCEDURE WriteNBytes(f              : File;
                      buffPtr        : ADDRESS;
                      requestedBytes : CARDINAL;
                  VAR written        : CARDINAL);
  (* Write requested bytes from buffer at address    *)
  (* 'buffPtr', number of effectively written bytes  *)
  (* is returned in 'written'                        *)

PROCEDURE ReadByte(f : File;      (* Read a byte from file *)
               VAR b : BYTE);

PROCEDURE WriteByte(f : File;      (* Write a word to file  *)
                    b : BYTE);

PROCEDURE EndFile(f : File) : BOOLEAN;
  (* returns true if an attempt has been made
     to read past the physical end of file   *)
\end{verbatim}
\continue
\newpage
\begin{verbatim}
PROCEDURE GetPos(   f : File;
                VAR p : CARDINAL);

PROCEDURE SetPos( f : File;
                  p : CARDINAL);
  (* GetPos and SetPos get and set the file position *)

PROCEDURE AccessTime(path     : ARRAY OF CHAR;
                     VAR time : CARDINAL;
                     VAR ok   : BOOLEAN);
  (* finds time of last access to named file *)

PROCEDURE ModifyTime(path     : ARRAY OF CHAR;
                     VAR time : CARDINAL;
                     VAR ok   : BOOLEAN);
  (* finds time of last modification to file *)

PROCEDURE StatusTime(path     : ARRAY OF CHAR;
                     VAR time : CARDINAL;
                     VAR ok   : BOOLEAN);
  (* finds time of last status change of file *)


PROCEDURE FileSize(filePath  : ARRAY OF CHAR;
                   VAR size  : CARDINAL;
                   VAR ok    : BOOLEAN);
  (* gets size of file "filePath" and returns it in "size" *)
 
END UxFiles.
\end{verbatim} } % end small
