Changes.os2

Oct 20 1993, Peter Bertelsen
Department of Computer Science, Technical University of Denmark.


Abstract
--------

This port of SML/NJ 0.93 is implemented under OS/2 using the Unix emulator emx.
Some changes to the runtime system C source files have been necessary to make
the runtime system compile and run supported by emx.
Due to limitations in OS/2 and emx, the available runtime services differ
slightly from the original Unix version of SML/NJ. This file describes the
changes to the runtime environment, as they appear to the ML programmer.


Interactive input
-----------------

When running SML/NJ under OS/2, the actual input handling (i.e. editing) is
supported directly by OS/2. This features normal DOS-style editing, i.e. <F3>
repeats last line of input, <F1> repeats last input character by character,
etc.

Use <Ctrl-Z> followed by <Enter> to terminate the system, instead of <Ctrl-D>.
The interactive loop terminates when end-of-file is reached (on std_in) and
<Ctrl-Z> is translated as EOF in OS/2 (and emx).

You may use <Ctrl-C> or <Ctrl-Break> to stop an infinite loop in ML, but please
note that this aborts the system (completely!), as signal handling is not
implemented in this port.


Exporting
---------

Exporting the current state with exportML and exporting a single function with
exportFn doesn't directly build an executable image. The exporting is simulated
by dumping a core image of the running process. The core image must then be
merged with the runtime executable to build an executable file.
For this purpose, the utility 'BindCore.cmd' is provided as a front-end to the
emx utility 'emxbind.exe'.

Having 'exported' the core image 'my.core', you can build an executable image
'my.exe', by issuing the command

   BindCore my.core my.exe

from the OS/2 command line prompt. The utility 'BindCore.cmd' in turn calls
'emxbind.exe' to merge the core image with an existing (a.out style) runtime
system executable 'run', and finally renames the executable image to 'my.exe'.


Stream I/O
----------

Stream I/O is complicated by emx text mode translation. In text mode input,
<CR/LF> (OS/2 newline sequence) is translated to <LF> (Unix style) and vice
versa on output. This is really necessary when processing source files and
other ASCII text files, but must be avoided when reading and writing mo-files!

A hack has been inserted into the runtime system to solve this. When opening a
stream with open_in or open_out, the file connected to the stream is opened in
binary mode (no translation) if the file name contains ".mo" as part of the
name. Unfortunately, this doesn't solve the problem for any other binary files.
If you have to read or write a file in binary mode, and the file name doesn't
contain ".mo", you definitely have a problem...

Apart from the exportML and exportFn functions already described, only IO
functions execute and execute_in_env don't work as intended (but don't hang the
system).


System.Unsafe.CInterface
------------------------

These C functions (in the runtime system) are not implemented:

   syscall
   connect_unix
   connect_inet
   link
   send_obd
   getdirent
   readlink
   chmod    (only implemented for file name argument)
   setitimer

Calling any of these via the c_function mechanism will raise exception
SysError. Calling via wrap_sysfn will just raise SystemCall instead.
Consequently, calling ML functions setitimer and syscall will also raise
exception SysError.

Like execute and execute_in_env (from IO), exec doesn't work as intended, but
doesn't hang the system.

Exporting with the export function is changed exactly like the exportML and
exportFn functions described previously.

Since OS/2 is a single-user platform, gethostname() always returns "PC",
getuid() and getgid() always returns 0, whereas gethostid() always returns ""
(empty string).

CPU time tracking isn't supported in OS/2 and gettime() returns real time
elapsed for usr and gc, but always 0 for sys. See also System.Timer.

Changing current directory with chdir, it is also possible put a drive name in
front of the path name, thereby switching to another disk drive.


System.Directory
----------------

Due to differences between Unix and OS/2 in accessing directories, the
functions listDir and getWD doesn't work and always raise exception
NotDirectory.


System.Signals
--------------

As signals are not implemented in this port, the functions in System.Signals
generally have no effect at all. However, pause() blocks the system, as no
signals will ever be received. The only way to 'wake up' the process is
pressing <Ctrl-C> or <Ctrl-Break>, thereby killing it!


System.Unsafe.SysIO
-------------------

Just like System.Unsafe.CInterface, this structure suffers from unimplemented C
functions, and these functions always raise exception SystemCall:

   connect_unix
   connect_inet
   link
   symlink
   send_obd
   getdirent
   readlink

The unlink function doesn't work with directories, but deletes normal files as
intended (since there's always exactly 1 'link' to each file in OS/2).

File I/O is complicated by emx text mode translation, just as stream I/O.
All comments on stream I/O apply to direct file I/O as well.

Changing access rights for a file with chmod only works for PATH arguments.
Furthermore, it's only possible to change the 'owner rights' of the file.
Specifying a DESC argument should raise exception SystemCall in this port, but
instead this causes an 'access violation' and the process is immediately killed
by OS/2!

To solve a problem in the interactive loop, a hack has been inserted into
fionread, always returning 0 for interactive fd 0 (std_in).

The getfid function should return a unique identifier for the queried file, but
since inode values aren't used in OS/2, every call returns a new identifier...

Due to differences in the Unix and OS/2 file systems, the file types F_SYMLINK
and F_BLK are never returned by ftype.

Since OS/2 is a single-user platform, getownid always returns (0,0).

Due to problems with select() in emx, the ML version of select always returns
(nil, nil, nil).


System.Timer
------------

As OS/2 doesn't support CPU time tracking like Unix, these timing functions in
System.Timer work differently:

   check_timer       Reports elapsed non-garbage collection real time since the
		     timer was started.
   check_timer_gc    Reports elapsed garbage collection real time since the
		     timer was started.
   check_timer_sys   Always reports 0.

From a physical point of view, this should mean that OS/2 runs at infinite
speed, but that may subject for discussion.

Strange timing results are sometimes reported after garbage collection and when
using the timing functions in System.Timer:  Negative elapsed times!
Either Einstein was a fraud or some kind of rounding (or another emx internal
timing error) makes timing very much inaccurate...
