
Using OOC under Win32
=====================

This document describes options for using OOC on Windows systems.

Currently, OOC requires the GNU C compiler (gcc). There are a couple of
implementations of gcc under Windows:

1) Mingw32  (www.mingw.org)
2) Cygwin   (www.cygwin.com)

Mingw32 is a "minimalist" implementation of gcc for Win32 systems. Mingw32
applications link to Microsoft's own C run-time library (MSVCRTL.DLL),
which is installed as part of every Windows system. Some features of
Mingw32:
- Mingw32 environment is compact.
- Mingw32 applications are compact.
- Run-time library functions have "Windows" semantics.
- Some "Unix" functionality is not available.

Cygwin is an implementation of the Unix API for Windows. Cygwin
applications use GCC's run-time library as well as additional "emulation"
functions in a separate library (CYGWIN.DLL). Some features of Cygwin:
- Cygwin environment is very large.
- Cygwin applications require an additional large DLL.
- Run-time library functions have "Unix" semantics.
- Cygwin is only free for GPL code. Use with non-GPL code requires a
  special contract with the vendors.

In many cases, Unix source code can run unmodified under Cygwin. Cygwin is
typically distributed with a large collection of Unix utilities, including:
- C compiler
- Bash shell
- ssh and cvs
- XWindows client libraries
- XWindows server
- inetd and friends (supporting ftp and telnet into Windows systems).

In addition, Cygwin supports the generation of Mingw applications via the
"-mno-cygwin" option. 

OOC supports the following options:

- Cygwin
- Mingw stand-alone  (with MSYS)
- Mingw under Cygwin

Note: Some of these configurations have not been extensively tested. Please
report any problems.

Path virtualisation
===================

The C compiler and associated utilities are Unix applications that have
been ported to run under Windows. Unix applications cannot be allowed to
see DOS file names, or they would fail to handle files properly. Each
application has its own file management procedures that assume Unix syntax.
To port such applications to Windows, the run-time environment MUST map all
DOS file paths to Unix syntax.

Applications compiled with Cygwin will see Unix-style paths. Applications
compiled with Mingw (or -mno-cygwin under Cygwin) will see Windows paths.

OOC will see different styles of paths according to which environment is
has been compiled under. However, the C compiler always sees virtual Unix
paths. For OOC and gcc to play nicely together:

  It is ESSENTIAL that OOC and gcc SEE THE SAME PATHS TO SOURCE FILES.

Keep this in mind when installing the system.

Note that OOC uses an absolute path to name the "install" program. This means
that the path detected by "configure" may not be usable by the generated
compiler under mingw. To remedy this problem, specify the absolute path using
the INSTALL environment variable.

Installation
============

1) Make a directory `c:\usr\local\src', and extract the oo2c files here.

2) Under MSYS or Cygwin, ensure that `c:\usr\local' is mapped to the
   logical path `/usr/local'. Normally, one would do:

     mount c:/usr/local /usr/local

   If you encounter problems with the "mount" tool, see additional comments
   below.

3) `cd' to the directory containing the compiler source code.

4) Configure the package.

    For Cygwin:

      env CFLAGS=-O2 ./configure --disable-libs

      
    For stand-alone Mingw32 (adjust path to "install.exe"):

	  env "INSTALL=c:/msys/1.0/bin/install.exe" CFLAGS=-O2 \
        ./configure --disable-libs

    For Mingw32 under Cygwin:

	  env CPPFLAGS=-mno-cygwin CFLAGS=-O2 LDFLAGS=-mno-cygwin \
	    ./configure --disable-libs

      (depending on path settings, INSTALL path may be required as above)

5) Type `make' to compile the package.

6) Type `make install' to install the programs and any data files and
   documentation.  `make install-strip' will additionally remove any 
   debug information from the installed executables.

7) You can remove the program binaries and object files from the
   source code directory by typing `make clean'.  To also remove the
   files that `configure' created (so you can compile the package for
   a different kind of computer), type `make distclean'.  

Problems?
=========

1) In at least one version of MSYS it looks like the "mount" tool is
   broken.  If you keep getting "Function not implemented", you may need to
   manually edit the MSYS fstab file (eg. C:\MSYS\1.0\etc\fstab). It should
   look something like this:

     c:/MinGW /mingw
     c:/usr/local /usr/local

   Note that MSYS must be restarted for any changes to take effect.

2) OOC couldn't find "install" during "make install"? Depending on path 
   settings, the detected path to "install" may not be valid for mingw
   executables. See the explanation in "Path Virtualisation" and try setting
   the INSTALL path before running "configure". For a quick fix, manually
   adjust the "install" entries in the generated "rsrc/OOC/oo2crc.xml" and
   re-run "make install".

Platform-specific issues
========================

This section discusses features of OOC relevant to the Win32 platform.

- Alignment. Many Win32 structure specify particular alignments. OOC
  provides the following record flags to control the alignment of fields
  within a record: ALIGN1 ALIGN2 ALIGN4 ALIGN8

  Example:

    tagMCI_WAVE_OPEN_PARMSA_struct* = RECORD [ALIGN1]
      dwCallback* : DWORD;
      wDeviceID* : MCIDEVICEID;
      lpstrDeviceType* : LPCSTR;
      lpstrElementName* : LPCSTR;
      lpstrAlias* : LPCSTR;
      dwBufferSeconds* : DWORD
    END;

- Calling Conventions. Most functions in the Win32 API are declared to use
  "Pascal" (or "stdcall") calling convention. For Pascal calls, the callee
  removes any parameters from the stack before returning from the
  procedure.  In "C" calling convention (or "cdecl"), the caller removes
  the parameters which permits the use of variable argument lists.

  OOC allows calling convention to be specified in both Module declarations
  and procedure declarations. For example, an interface module for a Win32
  library is usually declared "Pascal":

    MODULE WinApi [ INTERFACE "Pascal";
      LINK LIB "kernel32"; LIB "user32"; LIB "gdi32" END];

  Procedures or procedure types declared within the interface module will
  inherit the specified calling convention. 

    WNDPROC* = PROCEDURE (p0 : HWND; 
	   p1 : UINT; p2 : WPARAM; p3 : LPARAM) : LRESULT;

  In the above example, WinApi.WNDPROC inherits the "Pascal" convention
  declared in the module header.  Exceptions from the module convention may
  be declared per procedure. For example:

    PROCEDURE wsprintfA* [ "C" ] (p0 : LPSTR; p1 : LPCSTR; ...) : LONGINT;
 
  Regular Oberon-2 modules use the default calling convention, which is
  compatible with "C". Oberon-2 functions to be used as Win32 call-backs
  must therefore be explicitly declared "Pascal". For example:

    IMPORT W := WinApi;

    PROCEDURE MessageHandler ["Pascal"] (wnd : W.HWND; 
      msg : W.UINT; wParam : W.WPARAM; lParam : W.LPARAM) : W.LRESULT;

- C string assignment. Libraries written for the "C" language generally
  represent text strings using the "char *" data type. The Oberon-2
  equivalent is "POINTER TO ARRAY OF CHAR", which is not normally
  compatible with Oberon strings types. The CSTRING pointer flag specifies
  that "C"-style string assignments should be permitted. The following are
  fragments from the Win32 API.

    PCHAR* = POINTER [ CSTRING ] TO ARRAY OF CHAR;
	...
    LPCSTR* = PCHAR;
	...
    PROCEDURE MessageBoxA* (hWnd : HWND; 
	  lpText : LPCSTR; lpCaption : LPCSTR; uType : UINT) : LONGINT;

  The declaration of WinApi.MessageBoxA allows strings or character arrays
  to be passed as the second and third parameters. For example:

    IMPORT W := WinApi;

    PROCEDURE TestMessage;
    VAR result : LONGINT;
    BEGIN
      result := W.MessageBoxA(0, "Hello!", "This is a test Message", 0);
    END TestMessage;

    PROCEDURE MessageBox(title, message : ARRAY OF CHAR);
	VAR result : LONGINT;
	BEGIN
	  result := W.MessageBoxA(0, title, message, 0);
	END;  

Implementation Issues
=====================

1) File rename. 

Windows file semantics do not allow open files to be renamed, or files to
be renamed over existing files. Cygwin emulates Unix behaviour, but not on
Win9X platforms. 

- Files.File.Register uses unlink/rename/re-open

- IO:FileChannel uses the Win32 kernel function MoveFileEx to guarantee an
  atomic rename operation. It is not clear which versions of Windows
  support MoveFileEx. 

2) ftruncate()

The ftruncate function is unavailable under Windows. This means that
PosixFileDescr.Truncate will always return an error.

3) Windows networking.

Windows networking functions are in a separate library, WSOCK32.DLL, which
is included if the relevant IO modules are used.  The networking library is
configured as part of the initialisation for module IO:Socket. Note that
Windows sockets are not file descriptors and require a separate set of
functions to operate. For portable code, IO:SocketChannel should always be
used for sockets.

4) system()

There are many issues associated with the system() run-time function.
Under Unix, system() calls the Unix shell as its command interpreter.
Under windows, system() calls the Windows command interpreter. These
interpreters differ in their syntax and semantics. In addition, the
Microsoft C start-up code has its own rules for interpreting the command
line. 

There appear to be some limitations in the Windows command interpreter that
prevent OOC passing long command lines to the C compiler (eg. as are
required for static linking). Therefore, OS:ProcessManagement.system does
not use the run-time library system() command. Instead, the command-line is
passed directly to the command using the Win32 kernel CreateProcess
function. This means that it is not possible to:
- use piping redirection with a system command
- specify substitutions using environment variables

An option exists to use an external shell `/bin/sh' for the system command.
This can be enabled by defining USE_SHELL in lib/src/OS/ProcessManagement.c. 
With an external shell, such as `bash' installed in `C:\bin', system()
behaves the same as the Unix system() call. This configuration is necessary
to use the test framework from the OOC CVS repository. 

-- Stewart Greenhill <sgreenhill@users.sf.net>

